为描述符设置默认(初始)值
Set default (initial) value for descriptor
假设我们得到以下代码:
class NonNegative():
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__[self.name]
def __set__(self, instance, value):
instance.__dict__[self.name] = value
class Person:
fingerCount = NonNegative()
eyesCount = NonNegative()
def __init__(self, name):
self.name = name
p = Person("name")
print(p.fingerCount) <----- I want a default value printed here, instead of a KeyError
print(p.eyesCount) <----- ------ | | ------
我将如何分别为 fingerCount 和 eyesCount 分配默认(初始)值?
这样我就不必做:
p = Person("name")
p.fingerCount = 10
p.eyesCount = 2
print(p.fingerCount) # output: 10
print(p.eyesCount) # output: 2
,而是可以做到:
p = Person("name")
print(p.fingerCount) # output: 10
print(p.eyesCount) # output: 2
将默认值传递给 __init__
方法,当 instance.__dict__[self.name]
尚不存在时保存它以供使用。
class NonNegative():
<b>def __init__(self, v=0): # You may or may not want a default default value
self.dflt = v</b>
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__<b>.get(self.name, self.dflt)</b>
def __set__(self, instance, value):
instance.__dict__[self.name] = value
class Person:
fingerCount = NonNegative(10)
eyesCount = NonNegative(2)
def __init__(self, name):
self.name = name
如果愿意,您可以子类化 NonNegative
以提供特定于用例的默认值。
class FingerCount(NonNegative):
def __init__(self, v=10):
super().__init__(v)
class EyeCount(NonNegative):
def __init__(self, v=2):
super().__init__(v)
class Person:
fingerCount = FingerCount()
eyecount = EyeCount()
class Cyclops(Person):
eyecount = EyeCount(1)
如果您想要 属性 的每个实例的起始值,请像任何其他属性一样通过 __init__
中的 setter 初始化 属性。
class Person:
fingerCount = NonNegative()
eyesCount = NonNegative()
def __init__(self, fcount=10, ecount=2):
self.fingerCount = fcount
self.eyesCount = ecount
更静态的硬编码解决方案
class NonNegative:
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
if isinstance(instance, Person) and instance.__dict__.get('fingerCount') is None:
instance.fingerCount = 10
if isinstance(instance, Person) and instance.__dict__.get('eyesCount') is None:
instance.eyesCount = 2
return instance.__dict__[self.name]
def __set__(self, instance, value):
instance.__dict__[self.name] = value
class Person:
fingerCount = NonNegative()
eyesCount = NonNegative()
def __init__(self, name):
self.name = name
p = Person("name")
print(p.fingerCount)
print(p.eyesCount)
# 10
# 2
假设我们得到以下代码:
class NonNegative():
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__[self.name]
def __set__(self, instance, value):
instance.__dict__[self.name] = value
class Person:
fingerCount = NonNegative()
eyesCount = NonNegative()
def __init__(self, name):
self.name = name
p = Person("name")
print(p.fingerCount) <----- I want a default value printed here, instead of a KeyError
print(p.eyesCount) <----- ------ | | ------
我将如何分别为 fingerCount 和 eyesCount 分配默认(初始)值?
这样我就不必做:
p = Person("name")
p.fingerCount = 10
p.eyesCount = 2
print(p.fingerCount) # output: 10
print(p.eyesCount) # output: 2
,而是可以做到:
p = Person("name")
print(p.fingerCount) # output: 10
print(p.eyesCount) # output: 2
将默认值传递给 __init__
方法,当 instance.__dict__[self.name]
尚不存在时保存它以供使用。
class NonNegative():
<b>def __init__(self, v=0): # You may or may not want a default default value
self.dflt = v</b>
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__<b>.get(self.name, self.dflt)</b>
def __set__(self, instance, value):
instance.__dict__[self.name] = value
class Person:
fingerCount = NonNegative(10)
eyesCount = NonNegative(2)
def __init__(self, name):
self.name = name
如果愿意,您可以子类化 NonNegative
以提供特定于用例的默认值。
class FingerCount(NonNegative):
def __init__(self, v=10):
super().__init__(v)
class EyeCount(NonNegative):
def __init__(self, v=2):
super().__init__(v)
class Person:
fingerCount = FingerCount()
eyecount = EyeCount()
class Cyclops(Person):
eyecount = EyeCount(1)
如果您想要 属性 的每个实例的起始值,请像任何其他属性一样通过 __init__
中的 setter 初始化 属性。
class Person:
fingerCount = NonNegative()
eyesCount = NonNegative()
def __init__(self, fcount=10, ecount=2):
self.fingerCount = fcount
self.eyesCount = ecount
更静态的硬编码解决方案
class NonNegative:
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
if isinstance(instance, Person) and instance.__dict__.get('fingerCount') is None:
instance.fingerCount = 10
if isinstance(instance, Person) and instance.__dict__.get('eyesCount') is None:
instance.eyesCount = 2
return instance.__dict__[self.name]
def __set__(self, instance, value):
instance.__dict__[self.name] = value
class Person:
fingerCount = NonNegative()
eyesCount = NonNegative()
def __init__(self, name):
self.name = name
p = Person("name")
print(p.fingerCount)
print(p.eyesCount)
# 10
# 2