松V溪 发表于 2023-8-1 15:32:12

python魔法方法与描述符

本帖最后由 松V溪 于 2023-8-1 15:35 编辑

class Age:
    def __get__(self, obj, objtype=None):
      if obj.name == 'zhangsan':
            return 20
      elif obj.name == 'lisi':
            return 25
      else:
            return ValueError("unknow")

class Person:

    age = Age()

    def __init__(self, name):
      self.name = name

p1 = Person('zhangsan')
print(p1.age)   # 20

p2 = Person('lisi')
print(p2.age)   # 25

p3 = Person('wangwu')
print(p3.age)   # unknow

请问一下:
1,Python中魔法方法的触发条件是什么?
2,魔法方法和描述符之间有什么关系?
3,上面代码中我明明没有在Age里面定义obj对象,为什么还是可以对obj.name属性进行操作?
快来救救孩子吧{:10_266:} {:10_266:} {:10_266:}

Mike_python小 发表于 2023-8-1 15:44:34

松V溪 发表于 2023-8-1 12:39
请问一下:
1,Python中魔法方法的触发条件是什么?
2,魔法方法和描述符之间有什么关系?

1. 在Python中,魔法方法是由解释器在特定情况下自动调用的方法。它们以双下划线开头和结尾,比如__init__和__str__。每个魔法方法都有特定的触发条件,例如实例化对象时会调用__init__方法,使用print函数打印对象时会调用__str__方法。

2. 魔法方法和描述符之间存在一定的关系。描述符是一种实现属性访问控制的协议,而魔法方法可以在类中定义特殊行为。对于描述符来说,常用的魔法方法是__get__、__set__和__delete__,它们分别在获取属性值、设置属性值和删除属性时被调用。通过实现这些魔法方法,我们可以自定义属性的访问逻辑。

通常情况下,描述符的__get__、__set__和__delete__方法会被魔法方法调用,以实现属性的访问、赋值和删除。当我们访问一个属性时,解释器会首先查找该属性是否为描述符,如果是,则调用相应的魔法方法进行操作。因此,魔法方法提供了描述符中处理属性访问的入口点。

需要注意的是,并非所有的魔法方法都与描述符有直接的关系,魔法方法可以用于实现许多其他类相关的功能,比如操作符重载、上下文管理器等。

希望这回答了你的问题!如果你还有其他疑问,请随时提问。

如果回答对你有帮助,请给我一个最佳答案!{:10_254:}{:10_254:}{:10_254:}

陶远航 发表于 2023-8-1 15:32:33

你的代码中使用了描述符(descriptor)和类的魔法方法(magic method)。描述符是一种用于实现属性访问控制的协议,而魔法方法是在类中定义特殊行为的方法。

在你的代码中,Age是一个描述符类,实现了__get__方法。Person类中的age属性是一个Age实例。当你访问p1.age时,会调用Age类的__get__方法,并传递self(p1对象)作为参数。根据self.name的不同取值,__get__方法返回相应的年龄。

下面是修正后的代码:

class Age:
    def __get__(self, obj, objtype=None):
      if obj.name == 'zhangsan':
            return 20
      elif obj.name == 'lisi':
            return 25
      else:
            raise ValueError("unknown")

class Person:
    age = Age()

    def __init__(self, name):
      self.name = name

p1 = Person('zhangsan')
print(p1.age)   # 输出:20

p2 = Person('lisi')
print(p2.age)   # 输出:25

p3 = Person('wangwu')
print(p3.age)   # 引发 ValueError 异常,输出:unknown


修正后的代码中,当self.name为'zhangsan'时,__get__方法返回20;当self.name为'lisi'时,返回25;否则,引发ValueError异常。

请注意,描述符还有其他方法,如__set__和__delete__,用于实现属性的赋值和删除操作。你可以根据需要来实现这些方法。

如果你还有其他问题,请随时提问。
如果问题已经解决,请设置最佳答案

isdkz 发表于 2023-8-1 15:32:39

这段代码涉及到Python中的魔法方法和描述符(Descriptor)的概念。

魔法方法是Python中特殊的方法,它们以双下划线开头和结尾(例如 __init__ , __get__ 等),用于在特定情况下自动调用。描述符是一种自定义的属性访问方式,通过定义 __get__ 、 __set__ 和 __delete__ 方法,可以控制对类属性的访问。

在这段代码中,我们定义了一个 Age 描述符类,其中包含了 __get__ 方法,用于获取属性值。然后,我们创建了 Person 类,其中有一个 age 类属性,它使用了 Age 描述符。

当我们创建 Person 实例时,通过对 age 属性进行访问,Python会自动调用 Age 描述符的 __get__ 方法。在 __get__ 方法中,我们根据实例的 name 属性来返回相应的年龄。如果 name 为'zhangsan',返回20;如果 name 为'lisi',返回25;否则,返回一个 ValueError 异常,表示未知名字。

接下来,我们进行了一系列实例的测试:

1. 创建了名为 'zhangsan' 的 Person 实例 p1 ,然后打印 p1.age 。由于 p1.name 为 'zhangsan' ,所以通过 Age 描述符的 __get__ 方法返回了20。
2. 创建了名为 'lisi' 的 Person 实例 p2 ,然后打印 p2.age 。由于 p2.name 为 'lisi' ,所以通过 Age 描述符的 __get__ 方法返回了25。
3. 创建了名为 'wangwu' 的 Person 实例 p3 ,然后打印 p3.age 。由于 p3.name 既不是 'zhangsan' 也不是 'lisi' ,所以通过 Age 描述符的 __get__ 方法抛出了一个 ValueError 异常,表示未知名字。

这样,我们就了解了这段代码中描述符的作用以及魔法方法 __get__ 的调用时机和用法。

学习编程中的Ben 发表于 2023-8-1 15:33:28


class Age:
    def __get__(self, obj, objtype=None):
      if obj.name == 'zhangsan':
            return 20
      elif obj.name == 'lisi':
            return 25
      else:
            return ValueError("unknown")

class Person:
    age = Age()

    def __init__(self, name):
      self.name = name

p1 = Person('zhangsan')
print(p1.age)# 20

p2 = Person('lisi')
print(p2.age)# 25

p3 = Person('wangwu')
print(p3.age)# ValueError("unknown")


以上代码定义了两个类,`Age` 和 `Person`。`Age` 类实现了一个描述符,其中 `__get__` 方法根据 `obj` 对象的 `name` 属性返回对应的年龄值。

在 `Person` 类中,将 `age` 属性设置为 `Age` 的一个实例。在实例化 `Person` 对象时,会通过 `__init__` 方法传入一个名字,并将这个名字保存在对象的 `name` 属性中。

通过调用 `print` 函数打印不同 `Person` 对象的 `age` 属性,可以得到对应的年龄值。对于名字为 `'zhangsan'` 的对象,其年龄为 20;对于名字为 `'lisi'` 的对象,其年龄为 25;对于其他名字的对象,会抛出 `ValueError` 异常,提示 unknown(未知)。

这段代码展示了 Python 中使用描述符的一种方式,通过描述符可以在访问类属性时进行自定义操作。

松V溪 发表于 2023-8-1 15:39:54

陶远航 发表于 2023-8-1 15:32
你的代码中使用了描述符(descriptor)和类的魔法方法(magic method)。描述符是一种用于实现属性访问控制 ...

请问一下:
1,Python中魔法方法的触发条件是什么?
2,魔法方法和描述符之间有什么关系?

陶远航 发表于 2023-8-1 15:44:05

松V溪 发表于 2023-8-1 15:39
请问一下:
1,Python中魔法方法的触发条件是什么?
2,魔法方法和描述符之间有什么关系?

感谢您的提问,我会尽力为您解答。

1. Python中魔法方法的触发条件是什么?

魔法方法是一种特殊的方法,它们的名称以双下划线开头和结尾,例如 __init__ 或 __str__ 。魔法方法可以让你的类实现一些内置类型的行为,例如运算符重载、迭代、属性访问等。魔法方法的触发条件是当你对类或对象进行一些特定的操作时,Python会自动调用相应的魔法方法。例如:

- 当你创建一个类的实例时,Python会调用 __new__ 方法来分配内存空间,并调用 __init__ 方法来初始化实例属性。
- 当你打印一个对象时,Python会调用 __str__ 方法来返回对象的字符串表示。
- 当你使用 len 函数获取一个对象的长度时,Python会调用 __len__ 方法来返回对象中元素的个数。
- 当你使用 + 运算符对两个对象进行相加时,Python会调用 __add__ 方法来返回两个对象的和。

魔法方法的触发条件和具体功能取决于魔法方法的名称和定义。你可以在 中查看所有魔法方法的列表和说明。

2. 魔法方法和描述符之间有什么关系?

描述符是一种可以绑定到类属性上的对象,它可以控制属性的访问、赋值和删除。描述符本身也是一个类,它必须定义 __get__ 、 __set__ 和 __delete__ 中的至少一个方法。描述符可以让你实现一些高级功能,例如数据验证、属性缓存、代理等。描述符和魔法方法之间的关系是:

- 当你访问一个描述符属性时,Python会调用描述符类的 __get__ 方法来返回属性值。
- 当你赋值一个描述符属性时,Python会调用描述符类的 __set__ 方法来设置属性值。
- 当你删除一个描述符属性时,Python会调用描述符类的 __delete__ 方法来删除属性值。

因此,描述符是一种利用魔法方法来实现特殊行为的机制。你可以在 Python文档 中查看更多关于描述符的内容。

希望我的回答对您有所帮助。如果您还有其他问题,欢迎继续提问。
页: [1]
查看完整版本: python魔法方法与描述符