鱼C论坛

 找回密码
 立即注册
查看: 2052|回复: 6

[已解决]python魔法方法与描述符

[复制链接]
发表于 2023-8-1 15:32:12 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 松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属性进行操作?
快来救救孩子吧
最佳答案
2023-8-1 15:32:33
你的代码中使用了描述符(descriptor)和类的魔法方法(magic method)。描述符是一种用于实现属性访问控制的协议,而魔法方法是在类中定义特殊行为的方法。

在你的代码中,Age是一个描述符类,实现了__get__方法。Person类中的age属性是一个Age实例。当你访问p1.age时,会调用Age类的__get__方法,并传递selfp1对象)作为参数。根据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__,用于实现属性的赋值和删除操作。你可以根据需要来实现这些方法。

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

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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__方法会被魔法方法调用,以实现属性的访问、赋值和删除。当我们访问一个属性时,解释器会首先查找该属性是否为描述符,如果是,则调用相应的魔法方法进行操作。因此,魔法方法提供了描述符中处理属性访问的入口点。

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

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

如果回答对你有帮助,请给我一个最佳答案!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2023-8-1 15:32:33 | 显示全部楼层    本楼为最佳答案   
你的代码中使用了描述符(descriptor)和类的魔法方法(magic method)。描述符是一种用于实现属性访问控制的协议,而魔法方法是在类中定义特殊行为的方法。

在你的代码中,Age是一个描述符类,实现了__get__方法。Person类中的age属性是一个Age实例。当你访问p1.age时,会调用Age类的__get__方法,并传递selfp1对象)作为参数。根据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__,用于实现属性的赋值和删除操作。你可以根据需要来实现这些方法。

如果你还有其他问题,请随时提问。
如果问题已经解决,请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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__ 的调用时机和用法。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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 = namep1 = Person('zhangsan')print(p1.age)  # 20p2 = Person('lisi')print(p2.age)  # 25p3 = 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 中使用描述符的一种方式,通过描述符可以在访问类属性时进行自定义操作。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

请问一下:
1,Python中魔法方法的触发条件是什么?
2,魔法方法和描述符之间有什么关系?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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__ 方法来返回两个对象的和。

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

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

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

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

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

希望我的回答对您有所帮助。如果您还有其他问题,欢迎继续提问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-25 22:30

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表