2015-01-16 4 views
1

클래스 내에서 호출 유형 (dict) 함수 나는 다른 클래스에서 호출되는 .keys() 또는 .values ​​()와 같은 함수에 해당하는 클래스를 만들고 클래스 변수를 정의하려고합니다. 변하기 쉬운.클래스 변수 (파이썬 3.4)

class DATA(object): 
    def __init__(self, id, database = {}): 
     self.id = id 
     self.database = database 
     self.addresses = database.keys() 
     self.data = database.values() 

것은이 내가 클래스

foo = DATA(0,{"a":1,"b":2}) 

의 인스턴스를 만들 때와 같이 작업 한 후 요청하지 않는 것 :

print(foo.addresses) 
>>> [] 

하고 다시 준다 예를 들어 빈 목록.

참고 : 나는 모든 클래스 인스턴스의 빈 사전으로 시작 내 실제 프로그램에

후 나중에 나는 사전에 추가하는 함수를 사용합니다. 이 경우 ".database"는 여전히 작동하지만 ".addresses"는 호출하지 않습니다.

누구든지이 문제를 해결할 수 있습니까?

+0

나를 위해 작동합니다. – Joel

+0

@Brandon Gomes : 당신이 '다음에 묻는다'라고 말할 때 - 실제로 어떤 단계가 존재합니까? 실제로'foo = DATA (0, {})'로 시작하고 나중에 DATA.database를 변경 했습니까? –

답변

1

나는 이것이 문제가 될지 모르지만, {}와 같은 변경 가능 변수를 기본 인수로 사용하면 버그가 발생하는 경우가 많습니다. 참조 : "Least Astonishment" and the Mutable Default Argument

이 안전 :

def __init__(self, id, database=None): 
    if database is None: 
     self.database = {} 
    else: 
     self.database = database 

내가 DATA.addresses 및 DATA.data의 목적을 이해하지 않습니다. 중복을 피하기 위해 속성 데코레이터에 함수를 대신 사용할 수 있습니까?

@property: 
def addresses(self): 
    return self.database.keys() 

@property: 
def data(self): 
    return self.database.values() 
+0

감사합니다. 조건을 사용하는 것을 피했습니다. 왜냐하면 코드가 더 작고 빨라지기를 원했기 때문입니다. 제안을 사용하면 "키 속성이없는 NoneType"오류가 발생합니다. 만약 내가 단지 사전 이외의 데이터베이스를 사용하지 않을 것이기 때문에, 나는 변하기 쉬운 주장을 모두 없애면 효과가있을 것이라고 생각한다. –

+0

나는 이것이 그것을 설명한다고 생각하지 않는다. 나는'foo'를 정의하고 삭제 된 주소를 확인하는 사이에 여러분이 한 일이 있다고 생각합니다. 그러나이 방법으로 코드를 작성하는 것이 훨씬 더 좋은 생각입니다. – Joel

+0

if 블록으로 인해 코드가 느려지는 것을 염려하면 Donald Knuth의이 견적을 상기시켜야합니다. "프로그래머는 프로그램의 중요하지 않은 부분에 대해 생각하거나 걱정하지 않으려 고 막대한 시간을 낭비하고 디버깅과 유지 관리를 고려할 때 효율성에 대한 이러한 시도는 실제로 부정적인 영향을 미치므로 작은 효율성, 시간의 약 97 %를 말한다 : 조숙 한 최적화는 모든 악의 뿌리이다. 그러나 우리는 그 3 %에서 기회를 포기해서는 안된다. " –

1

문제는 당신이 당신의 __init__ 방법 keys 권리를 호출하고 결과를 저장하고 있다는 것입니다. 대신 액세스하려는 경우 keys으로 전화하십시오.

이제 클래스 요구 사항에 따라 몇 가지 방법으로이 작업을 수행 할 수 있습니다.

전화 코드를 변경하는 것이 마음에 드신다면 foo.addresses 대신 foo.database.keys()을 사용하면 매우 간단 할 수 있습니다. 후자는 포함 할 모든 정보가 databases 속성의 메소드를 통해 이미 사용 가능하므로 존재할 필요가 없습니다.

또 다른 방법은 (그것을 호출하지 않고) 당신의 DATA 객체의 인스턴스 변수에 바인딩 된 인스턴스 메서드 database.keys을 저장하는 것입니다 : 대신 foo.addresses의 당신이 foo.addresses()를 사용하는 것,

class DATA(object) 
    def __init__(self, database=None): 
     if database is None: 
      database = {} 
     self.database = database 
     self.addresses = database.keys # don't call keys here! 

호출 코드의 (a 함수 호출이 아니라 속성 조회). 이것은 실제로는 아니지만 DATA 인스턴스의 메소드 호출과 비슷합니다. 이미 데이터베이스 사전에 바인딩 된 메서드를 호출하고 있습니다. 다른 코드가 database 사전을 완전히 바꿀 수있는 경우 (단지 제자리에서 돌연변이가 아닌)이 작업이 중단 될 수 있습니다.

class DATA(object) 
    def __init__(self, database=None): 
     if database is None: 
      database = {} 
     self.database = database 
     # don't save anything as "addresses" here 

    @property 
    def addresses(self): 
     return self.database.keys() 

이 가장 할 수는을 할 수 있기 때문에, :

마지막 방법은 사용자가 DATA 인스턴스의 addresses 속성에 액세스하려고 할 때 데이터베이스 딕셔너리에서 keys를 요청하는 property를 사용하는 것입니다 호출 코드는 속성과 마찬가지로 addresses을 처리합니다. database 개체를 다른 코드 (예 : foo.database = {"foo":"bar"})로 완전히 바꾸면 제대로 작동합니다. 하지만 다른 접근 방식에서는 필요없는 추가 함수 호출이 있기 때문에 조금 느려질 수 있습니다.