2013-07-22 6 views
1

У меня есть класс, где я хочу быть в состоянии проверить его членов и перечислить их. Тем не менее, я только собираюсь подклассифицировать это (в C++ это будет абстрактный класс), поэтому я хочу, чтобы этот метод также возвращал члены в свой дочерний класс.Доступ к ребенку __dict__ от родителя в Python?

Возможно ли это или даже хорошая идея в Python? И продолжение, возможно ли это без модуля inspect?

Как так:

class A: 
    @staticmethod 
    def GetMembers(): 
     return dict(vars(A)) 

class B(A): 
    FOO = 'foobar' 
    BAR = 'barfoo' 

Однако тестирование показывает:

>>> A.GetMembers() 
{'__module__': '__main__', '__doc__': None, 'GetMembers': <staticmethod object at 0x02219BB0>} 
>>> B.GetMembers() 
{'__module__': '__main__', '__doc__': None, 'GetMembers': <staticmethod object at 0x02219BB0>} 
>>> dict(vars(B)) 
{'__module__': '__main__', 'FOO': 'foobar', 'BAR': 'barfoo', '__doc__': None} 

Я хочу B.GetMembers() включить FOO и BAR как dict(vars(B)) делает.

+0

Используйте [ '@ classmethod'] (http://docs.python.org/2/library/functions.html#classmethod) вместо '@ staticmethod' и проверьте параметр' cls'. Ваше ограничение «без модуля проверки» не имеет смысла - это модуль, для которого нужно проверять объекты «отражением», почему вы не хотите его использовать? И последнее, но не менее важное: в вашем примере кода 'FOO' и' BAR' являются членами объекта класса 'B' - это ** не ** члены экземпляров' B'. Нет общего способа перечисления атрибутов экземпляров класса, не прибегая к самим примерам. – millimoose

+0

Есть способы обойти последнее, используя определенные шаблоны, например, используя [слоты] (http://docs.python.org/2/reference/datamodel.html#slots), [named tuples] (http: // docs .python.org/2/library/collections.html # collections.namedtuple) или [traits] (http://code.enthought.com/projects/traits/) - или любым другим способом, в котором вы явно добавляете какой-либо вид метаданные для ваших классов. Просто не для какого-либо объекта вообще. – millimoose

+0

@staticmethod ужасно ... Я никогда не вижу причин использовать его ... –

ответ

5

@staticmethods не осведомлены о классе и классе ... поэтому не было способа, чтобы статический метод знал, что он был вызван в дочернем классе.

@classmethods получают свой тип класса в качестве первого аргумента (так же, как instancemethods получают себя как первый аргумент) ... вы можете затем вызвать что-либо на своих cls.

class A: 
    @classmethod 
    def GetMembers(cls): 
     return dict(vars(cls)) 

class B(A): 
    FOO = 'foobar' 
    BAR = 'barfoo' 

Тестирование

>>> A.GetMembers() 
{'__module__': '__main__', '__doc__': None, 'GetMembers': <classmethod object at 
0x0286D130>} 
>>> B.GetMembers() 
{'__module__': '__main__', 'FOO': 'foobar', 'BAR': 'barfoo', '__doc__': None} 
>>> 

в качестве альтернативы вы можете также получить доступ к родительским классам dicts. из метода класса (или экземпляр), вы можете получить доступ к BASECLASSES через cls.__bases__

class A: 
    @classmethod 
    def GetMembers(cls): 
     d = dict() 
     for basecls in cls.__bases__: 
     if hasattr(basecls,"GetMembers"): 
      d.update(basecls.GetMembers()) #call inherited GetMembers 
     else: 
      d.update(dict(vars(basecls))) #no GetMembers inherited from basecls so just get its vars 
     d.update(dict(vars(cls))) 
     return d 

>>> class B(A): 
...  FOO = 'foobar' 
...  BAR = 'barfoo' 
... 
>>> class C(A): 
...  FOOBAR = "whatever" 
... 
>>> class X(B,A): 
...  FOO = 'foobar2' 
...  COLOR = 'red' 
... 
>>> class X(B,C): 
...  FOO = 'foobar2' 
...  COLOR = 'red' 
... 
>>> X.GetMembers() 
{'__module__': '__main__', 'BAR': 'barfoo', 'COLOR': 'red', 'FOOBAR': 'whatever' 
, 'FOO': 'foobar2', '__doc__': None} 
+0

отлично, спасибо! – Nate

+0

приятно, позаботиться, чтобы объяснить, что происходит для нас, учеников ?, upvote в любом случае – Stephan

+0

там я дал немного больше объяснения –

Смежные вопросы