[英]How to define similar class-functions related to different class-properties inside __init__
[英]How to define properties in __init__
我想從成員函數中定義類中的屬性。 下面是一些測試代碼,顯示了我希望如何工作。 但是我沒有得到預期的行為。
class Basket(object):
def __init__(self):
# add all the properties
for p in self.PropNames():
setattr(self, p, property(lambda : p) )
def PropNames(self):
# The names of all the properties
return ['Apple', 'Pear']
# normal property
Air = property(lambda s : "Air")
if __name__ == "__main__":
b = Basket()
print b.Air # outputs: "Air"
print b.Apple # outputs: <property object at 0x...>
print b.Pear # outputs: <property object at 0x...>
我怎么能讓這個工作?
你需要在類上設置屬性(即: self.__class__
),而不是在對象上(即: self
)。 例如:
class Basket(object):
def __init__(self):
# add all the properties
setattr(self.__class__, 'Apple', property(lambda s : 'Apple') )
setattr(self.__class__, 'Pear', property(lambda s : 'Pear') )
# normal property
Air = property(lambda s : "Air")
if __name__ == "__main__":
b = Basket()
print b.Air # outputs: "Air"
print b.Apple # outputs: "Apple"
print b.Pear # outputs: "Pear"
對於它的價值,在循環中創建lamdas時使用p
不會給出你期望的行為。 由於p
的值在循環中被改變,因此循環中設置的兩個屬性都返回相同的值: p
的最后一個值。
這樣做你想要的:
class Basket(object):
def __init__(self):
# add all the properties
def make_prop( name ):
def getter( self ):
return "I'm a " + name
return property(getter)
for p in self.PropNames():
setattr(Basket, p, make_prop(p) )
def PropNames(self):
# The names of all the properties
return ['Apple', 'Pear', 'Bread']
# normal property
Air = property(lambda s : "I'm Air")
if __name__ == "__main__":
b = Basket()
print b.Air
print b.Apple
print b.Pear
另一種方法是做一個元類......但是它們讓很多人感到困惑^^。
因為我很無聊:
class WithProperties(type):
""" Converts `__props__` names to actual properties """
def __new__(cls, name, bases, attrs):
props = set( attrs.get('__props__', () ) )
for base in bases:
props |= set( getattr( base, '__props__', () ) )
def make_prop( name ):
def getter( self ):
return "I'm a " + name
return property( getter )
for prop in props:
attrs[ prop ] = make_prop( prop )
return super(WithProperties, cls).__new__(cls, name, bases, attrs)
class Basket(object):
__metaclass__ = WithProperties
__props__ = ['Apple', 'Pear']
Air = property(lambda s : "I'm Air")
class OtherBasket(Basket):
__props__ = ['Fish', 'Bread']
if __name__ == "__main__":
b = Basket()
print b.Air
print b.Apple
print b.Pear
c = OtherBasket()
print c.Air
print c.Apple
print c.Pear
print c.Fish
print c.Bread
為什么要在__init__
時定義屬性? 它令人困惑和聰明,所以你最好有一個很好的理由。 Stef指出的循環問題只是為什么應該避免的一個例子。
如果需要重新定義子類具有哪些屬性,則可以在子類__init__
方法中執行del self.<property name>
,或在子類中定義新屬性。
還有,一些風格的挑剔:
PropNames
- > prop_names
PropNames
實際上不一定是一種方法
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.