Python 3.x - 使用 setattr/getattr 与内部值的属性描述符
Python 3.x - Attribute descriptor using setattr/getattr vs internal value
我是 Python 描述符的新手。下面的问题是为了帮助我更好地理解它们是如何工作的。
在Python3.x中,我使用的是属性描述符。这个描述符的特殊之处在于它的 set 方法包含大量健全性检查,以确保要设置到属性的值遵守某些规则。构造函数使用 setattr 和 getattr 来操作属性。构造函数运行良好,其代码报告如下。
class AttributeDescriptor(): <----- Version 001 of this class
def __init__(self, attname):
self.__attname = "__" + attname
def __set__(self, obj, attvalue):
#Some data quality checks, not provided here...
setattr(obj, self.__attname, attval)
def __get__(self, obj, owner):
return getattr(obj, self.__attname)
class Hobbit():
def __init__(self):
pass
name = AttributeDescriptor("name")
sam = Hobbit()
merry = Hobbit()
sam.name = "Sam"
merry.name = "Merry"
print(sam.name) ----> Returns "Sam"
print(merry.name) ----> Returns "Merry"
print(sam.name) ----> Returns "Sam"
我还尝试使用以下代码定义构造函数,它为 "name" 属性返回了错误的值。事实上,所有霍比特人的名字都被设置为等于已定义的姓氏。
class AttributeDescriptor(): <---- Version 002 of this class
def __set__(self, obj, attvalue):
#Some data quality checks, not provided here...
self.value = attvalue
def __get__(self, obj, owner):
return self.value
class Hobbit():
def __init__(self):
pass
name = AttributeDescriptor()
sam = Hobbit()
merry = Hobbit()
sam.name = "Sam"
merry.name = "Merry"
print(sam.name) ----> Returned "Merry"
print(merry.name) ----> Returned "Merry"
print(sam.name) ----> Returned "Merry"
我的问题是:为什么描述符版本 002 设置 "name" 等于其所有实例中的公共值?
根据我对描述符的理解,描述符版本 001 会将名称存储在 Person 对象实例的属性中:
sam.__name = "sam"
merry.__name = "merry"
而描述符版本 002 会将名称存储在 Person 对象实例的 属性 的一个属性中:
same.name.value = "sam"
merry.name.value = "merry"
因此,对于 Python 描述符的工作原理,显然有一些我不明白的地方。任何人都可以向我提供一些说明吗?
在您的第二个示例中,您正在为 AttributeDescriptor 实例本身设置值。
您的程序中只有一个 AttributeDescriptor() 实例,因此每次您使用他的 set 方法时它都会更改相同的值
class霍比特人():
def __init__(self):
pass
name = AttributeDescriptor("name") # <---- happens ONLY once!!!
python 中的 class 定义只发生*一次 ...
*除非没有。但是让我们坚持更简单的真相:)
我是 Python 描述符的新手。下面的问题是为了帮助我更好地理解它们是如何工作的。
在Python3.x中,我使用的是属性描述符。这个描述符的特殊之处在于它的 set 方法包含大量健全性检查,以确保要设置到属性的值遵守某些规则。构造函数使用 setattr 和 getattr 来操作属性。构造函数运行良好,其代码报告如下。
class AttributeDescriptor(): <----- Version 001 of this class
def __init__(self, attname):
self.__attname = "__" + attname
def __set__(self, obj, attvalue):
#Some data quality checks, not provided here...
setattr(obj, self.__attname, attval)
def __get__(self, obj, owner):
return getattr(obj, self.__attname)
class Hobbit():
def __init__(self):
pass
name = AttributeDescriptor("name")
sam = Hobbit()
merry = Hobbit()
sam.name = "Sam"
merry.name = "Merry"
print(sam.name) ----> Returns "Sam"
print(merry.name) ----> Returns "Merry"
print(sam.name) ----> Returns "Sam"
我还尝试使用以下代码定义构造函数,它为 "name" 属性返回了错误的值。事实上,所有霍比特人的名字都被设置为等于已定义的姓氏。
class AttributeDescriptor(): <---- Version 002 of this class
def __set__(self, obj, attvalue):
#Some data quality checks, not provided here...
self.value = attvalue
def __get__(self, obj, owner):
return self.value
class Hobbit():
def __init__(self):
pass
name = AttributeDescriptor()
sam = Hobbit()
merry = Hobbit()
sam.name = "Sam"
merry.name = "Merry"
print(sam.name) ----> Returned "Merry"
print(merry.name) ----> Returned "Merry"
print(sam.name) ----> Returned "Merry"
我的问题是:为什么描述符版本 002 设置 "name" 等于其所有实例中的公共值?
根据我对描述符的理解,描述符版本 001 会将名称存储在 Person 对象实例的属性中:
sam.__name = "sam"
merry.__name = "merry"
而描述符版本 002 会将名称存储在 Person 对象实例的 属性 的一个属性中:
same.name.value = "sam"
merry.name.value = "merry"
因此,对于 Python 描述符的工作原理,显然有一些我不明白的地方。任何人都可以向我提供一些说明吗?
在您的第二个示例中,您正在为 AttributeDescriptor 实例本身设置值。
您的程序中只有一个 AttributeDescriptor() 实例,因此每次您使用他的 set 方法时它都会更改相同的值
class霍比特人():
def __init__(self):
pass
name = AttributeDescriptor("name") # <---- happens ONLY once!!!
python 中的 class 定义只发生*一次 ...
*除非没有。但是让我们坚持更简单的真相:)