Python 设置描述符的默认(初始)值
假设我们得到了以下代码:Python 设置描述符的默认(初始)值,python,object,properties,instance,descriptor,Python,Object,Properties,Instance,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 __s
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) <----- ------ | | ------
,但我们只能做到:
p = Person("name")
print(p.fingerCount) # output: 10
print(p.eyesCount) # output: 2
将默认值传递给uuu init uuuu方法,该方法将保存该值,以便在instance.uuu dict_uuu[self.name]尚不存在时使用
class NonNegative():
def __init__(self, v=0): # You may or may not want a default default value
self.dflt = v
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__.get(self.name, self.dflt)
def __set__(self, instance, value):
instance.__dict__[self.name] = value
如果愿意,可以将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
你知道,我确实考虑过这个问题,但我不认为它会起作用,因为Person类的所有实例都共享同一个非负描述符实例。问题:既然Person类的所有实例都共享同一个非负描述符实例,那么怎么可能有不同的self.dflt值?!你没有,这不是一个问题,只要你处理的是不可变的默认值。默认值仅在基础属性在实例字典中尚不存在时使用,根据定义,它是属性的一部分,而不是访问属性的实例。
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