【问题标题】:Python 3.x - Attribute descriptor using setattr/getattr vs internal valuePython 3.x - 使用 setattr/getattr 与内部值的属性描述符
【发布时间】:2016-02-03 18:19:14
【问题描述】:

我是 Python 描述符的新手。下面的问题是为了帮助我更好地理解它们的工作原理。

在 Python 3.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 为何在所有实例中都将“名称”设置为一个公共值?

根据我对描述符的理解,描述符版本 001 会将名称存储在 Person 对象实例的属性中:

sam.__name = "sam"
merry.__name = "merry"

而描述符版本 002 会将名称存储在 Person 对象实例的属性的属性中:

same.name.value = "sam"
merry.name.value = "merry"

因此,对于 Python 描述符的工作原理,我显然有一些不明白的地方。谁能给我一些澄清?

【问题讨论】:

    标签: class python-3.x attributes instance descriptor


    【解决方案1】:

    在您的第二个示例中,您正在设置 AttributeDescriptor 实例本身的值。

    你的程序中只有一个 AttributeDescriptor() 实例,每次你使用他的 set 方法时它都会改变相同的值

    类霍比特人():

      def __init__(self):
    
         pass
    
      name = AttributeDescriptor("name") # <---- happens ONLY once!!!
    

    python 中的类定义只发生*一次 ...

    *除非没有。但是让我们坚持更简单的真相:)

    【讨论】:

    • 我们走了!我不知道。它解释了一切。谢谢。 :)
    • “name”属性和 AttributeDescriptor 实例是同一个东西还是两个不同的东西?属性“名称”是连接到“AttributeDescriptor”类的另一个对象的不同实体吗? ...只是想了解
    • 如果我在“Hobbit”类中有另一个属性怎么办:age = AttributeDescriptor("age")。这会创建另一个“AttributeDescriptor”实例,还是 self.__attvalue 会被这个新属性名称覆盖?
    • 这将是一个新的。 -顺便说一句,您可以将打印添加到类 _init_ 方法中,然后查看它被调用了多少次
    猜你喜欢
    • 2014-04-05
    • 2012-10-02
    • 1970-01-01
    • 1970-01-01
    • 2014-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多