资讯专栏INFORMATION COLUMN

Python (类)实例方法的特殊属性

shiina / 1956人阅读

摘要:类实例方法,本身也是这与实例方法一致只不过,一个是绑定类类实例,另一个是绑定实例。

自定义函数的特殊属性已经专门整理过一篇(Python 自定义函数的特殊属性),方法的特殊属性与其稍有不同,我们通过下面这个例子展开介绍:

class A():

    def foo(self):
        """a method"""
        print("hellow world!")
    
    bar = foo
    
    @classmethod
    def clsmtd(cls, arg):
        print(str(arg))   
    
a = A()
实例方法的只读属性

与自定义函数的特殊属性相比,实例方法具有 __self__,__func__ 这两个函数所不具有的只读属性;此外,方法的 __doc__,__name__,__module__ 也是只读。对于实例方法而言,其 __self__ 属性为实例本身:

print(a.foo.__self__)
# <__main__.A object at 0x00000233DF6DE2E8>
print(a)
# <__main__.A object at 0x00000233DF6DE2E8>

__func__ 属性则返回方法所对应的底层函数:

print(a.foo)
# >
print(a.foo.__func__)  #注意与 a.foo 的区别
# 

至于 __doc__,__name__,__module__ 属性则与函数相应属性的值一致,所不同的是方法的这些属性均为只读,不可改写:

print(a.foo.__doc__)
# a method

print(a.foo.__name__)
# foo

print(a.foo.__module__)
# __main__
实例方法可通过底层函数访问函数属性

不过,实例方法也可以通过其底层的 function 对象(通过 __func__ 属性获得)访问函数所具有的特殊属性,如:

print(a.foo.__func__.__code__)
# ", line 3>

因此,诸如 __doc__,__name__,__module__等属性的值就可以通过底层函数相应的特殊属性进行改写:

a.foo.__doc__ = "raise error"
# AttributeError: attribute "__doc__" of "method" objects is not writable

print(a.foo.__func__.__doc__)
# a method
a.foo.__func__.__doc__ = "can be changed through func doc"
print(a.foo.__doc__)
# can be changed through func doc


a.foo.__name__ = "dobi"
# AttributeError: "method" object has no attribute "__name__"

print(a.foo.__func__.__name__)
# foo
a.foo.__func__.__name__ = "dobi"
print(a.foo.__name__)
# dobi
底层函数的唯一性

需要注意的是:当一个类的实例方法是通过其他实例方法创建,则其他实例方法所对应的底层函数并非其所创建的实例方法,而是其所创建的实例方法所对应的底层函数:

print(a.bar) #注意这里 a.bar 是个实例方法
>
print(a.bar.__func__)
# 

上例中,通过其他实例方法 a.bar 创建了实例方法 a.foo,但a.bar.__func__ 却是 a.foo.__func__ 而非 a.foo

print(a.foo.__func__)
# 
print(a.foo)
# >
实例方法的首位参数为实例本身

实例方法执行时,其底层函数的首位参数为实例本身,下面两行代码执行结果是一致的:

a.foo()
# hellow world!
a.foo.__func__(a)
# hellow world!
类实例方法的首位参数是类本身

当一个实例方法(严格来说是类实例方法)是由类方法创建,则其 __self__ 属性是其类本身:

print(a.clsmtd.__self__)
# 

事实上,通过类方法建立的(类)实例方法,在调用底层函数时(下例是 A.clsmtd.__func__),其首位参数(也即 __self__)是类本身,这一点与实例方法执行时有所区别。

a.clsmtd("dog")
# dog
A.clsmtd("dog")
# dog
A.clsmtd.__func__(A, "dog")
# dog

类实例方法,本身也是 bound method,这与实例方法一致:

print(a.clsmtd)
# >
print(a.foo)
# >
print(A.clsmtd)
# >
print(A.foo)
# 

只不过,一个是绑定类(类实例),另一个是绑定实例。

总结

Python 3 有两种 bound method, 一种是 instance method,一种是 class methodclass instance method),两种都可以被实例访问;

对于 instance method__self__ 属性值为 instance 本身,而 class method 其属性值则为 class 本身;

不管是 instance method 还是 class method ,执行时,都需要调用与之对应的底层函数(underlying function,通过 __func__ 访问),底层函数的首位参数通过 __self__ 获得, 对于 instance method 其为该实例本身,对于 class method 则为该类本身;

bound method 可以通过对应的底层函数,访问函数的所有特殊属性。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/38004.html

相关文章

  • Python学习之路28-符合Python风格对象

    摘要:本篇继续学习之路,实现更多的特殊方法以让自定义类的行为跟真正的对象一样。之所以要让向量不可变,是因为我们在计算向量的哈希值时需要用到和的哈希值,如果这两个值可变,那向量的哈希值就能随时变化,这将不是一个可散列的对象。 《流畅的Python》笔记。本篇是面向对象惯用方法的第二篇。前一篇讲的是内置对象的结构和行为,本篇则是自定义对象。本篇继续Python学习之路20,实现更多的特殊方法以让...

    Eric 评论0 收藏0
  • Python标准库---16、内置型:上下文管理器型、其他、特殊属性

    摘要:退出运行时上下文并返回一个布尔值旗标来表明所发生的任何异常是否应当被屏蔽。除了实现上下文管理协议以外,不同类型不会被特殊处理。其中一些并不会被内置函数所列出。 上一篇文章:Python标准库---15、内置类型:集合类型、映射类型下一篇文章:Python标准库---17、内置异常 上下文管理器类型 Python 的 with 语句支持通过上下文管理器所定义的运行时上下文这一概念。 此...

    zhisheng 评论0 收藏0
  • Python动态属性和特性

    摘要:一利用动态属性处理数据源属性在中,数据的属性和处理数据的方法统称属性。处理无效属性名在中,由于关键字被保留,名称为关键字的属性是无效的。内置函数列出对象的大多数属性。点号和内置函数会触发这个方法。 导语:本文章记录了本人在学习Python基础之元编程篇的重点知识及个人心得,打算入门Python的朋友们可以来一起学习并交流。 本文重点: 1、了解如何利用动态属性处理数据;2、掌握Pyth...

    scola666 评论0 收藏0
  • SICP Python 描述 2.6 实现和对象

    摘要:以这种方式实现对象系统的目的是展示使用对象隐喻并不需要特殊的编程语言。我们的实现并不遵循类型系统的明确规定。反之,它为实现对象隐喻的核心功能而设计。是分发字典,它响应消息和。 2.6 实现类和对象 来源:2.6 Implementing Classes and Objects 译者:飞龙 协议:CC BY-NC-SA 4.0 在使用面向对象编程范式时,我们使用对象隐喻来指导程序...

    chenjiang3 评论0 收藏0
  • python基础教程:

    摘要:类对象被创建时存在于类命名空间内的所有名称都是有效的属性名称。类的实例化,是使用函数表示法,可以把类对象看做是会返回一个新的类实例的函数。这就是可变对象作为类变量时的特性。类变量是所有类的实例共享的属性和方法,实例变量是每个实例独有的数据。 Python是面向对象的高级编程语言,在Python里面一切都是对象:数字、字符串、元组、列表、字典、集合等内置数据类型,以及函数、方法、类、模块...

    fish 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<