파이썬에서 클래스, 함수, 전역에 변수 있는지 확인하기 (+ 함수의 스코프)

ilotoki·2023년 7월 8일
0

except 사용하기

우선 코드를 돌려 보고 오류 코드에 맞추어 except문을 만드는 것이 사실 가장 간편한 방법이다. 절대 나쁜 방식이라고 할 수는 없다.

foo = 'hello' # 없어도 버그가 나지 않음
try:
	print(foo)
except NameError:
	pass

만약 except 뒤에 달리 처리해야 할 것이 없다면(그저 pass로 넘기기만 한다면) contextlib.suppress를 이용하는 것도 좋다. 장점은 깔끔하다는 것이고 단점은 contextlib.suppress를 모르는 초보 개발자에게 혼란을 야기할 수 있다는 점과 귀찮게 import를 해야 한다는 점 정도이다.

from contextlib import suppress

foo = 'hello' # 없어도 버그가 나지 않음
with supress(NameError):
	print(foo)

각종 함수 사용하기

아까보다는 조금 복잡하다. 우선 알아보기 전에 클래수, 함수, 전역의 변수 범위를 알아야 한다.

foo = 0


def hello():
    bar = 1


class World:
    google = 3

    def __init__(self):
        self.baz = 2
        Korea = 4

    def America(self):
        print(self.baz)  # 문제 없음
        print(Korea)  # NameError
        print(World.google) # 문제 없음

이 코드에서 foo는 아무런 indent도 되지 않은 곳에서 선언되었기 때문에 전역 변수이고 이는 전역 스코프(scope)에 존재한다고 말한다.
bar는 hello의 범위 안에 있고 따라서 hello의 지역 변수라고 한다.
self.baz는 World의 인스턴스 변수이다. 이는 __init__의 지역 변수의 Korea와 대조적으로, 함수의 인스턴스 내에서 누구든지 사용할 수 있다. 예를 들어, America 메소드에서 self.baz를 불러올 수 있지만 Korea는 아니다.

전역 스코프에서 변수 확인하기

전역 스코프에서는 globals()를 이용해 변수를 확인할 수 있다.

# 이전의 코드에서 이어짐

# 변수 foo가 전역 스코프에 있는지 확인
print('foo' in globals()) # True

이때 주의해야 할 것은 foo in globals()가 아닌 'foo' in globals()라는 것이다. foo in globals()라고 하면 foo안에 있는 값이 globals와 비교되기에 (즉, 0 in globals()라고 물은 꼴이다) 'foo'를 사용해야 한다.

함수의 스코프에서 변수 확인하기

함수, 즉 지역 스코프에서는 locals()globals()를 동시에 사용해야 한다.

# 변수 bar이 지역 스코프나 전역 스코프에 있는지 확인
def hello():
    bar = 1
    print('bar' in locals() or 'bar' in locals()) # True

둘 모두 살펴봐야 하는 이유는 지역 스코프에 변수가 없으면 전역 스코프에 변수가 있는지 확인하게 되기 때문이다.

클래스에서 변수 확인하기

인스턴스 변수와 클래스 변수의 확인은 hasattr()를 사용할 수 있다.

class World:
    google = 3

    def __init__(self):
        self.baz = 2
        Korea = 4

    def America(self):
        print(self.baz)  # 문제 없음
        # print(Korea)  # NameError

        print(World.google)  # 문제 없음
        print(self.google)
        print(hasattr(self, "baz"))  # True, self.baz 존재함
        print(hasattr(self, "google"))  # True, self.google 존재함
        print(hasattr(World, "google"))  # True, World.google 존재함

주의할 것은 클래스 변수는 인스턴스 변수로도 사용이 가능하다는 점이다. 즉, 클래스 변수인 World.google은 self.google로도 불러올 수 있고 hasattr도 이를 반영한다는 것이다. 만약 한 변수가 클래스 변수인지 인스턴스 변수인지 확인하려면 클래스에 해당 변수가 있는지 확인해야 한다.

0개의 댓글