专栏首页极客起源Python编程思想(24):类的实例方法

Python编程思想(24):类的实例方法

对于在类中定义的实例方法,Python会自动绑定方法的第1个参数(通常是self),第1个参数总是指向调用该方法的对象。由于实例方法(包括构造方法)的self参数会自动绑定,因此程序在调用普通实例方法、构造方法时不需要为第1个参数传值。

self参数最大的作用就是引用当前方法的调用者,比如在构造方法中通过self为该对象增加实例变量。也可以在一个实例方法中访问该类的另一个实例方法或变量。假设定义了一个Bird类,这个Bird对象的move()方法需要调用它的fly()方法,此时就可通过self参数作为 fly()方法的调用者。

方法的第1个参数所代表的对象是不确定的,但它的类型是确定的。它所代表的只能是当前类的实例;只有当这个方法被调用时,它所代表的对象才被确定下来。也就是说,谁在调用这个方法,方法的第1个参数就代表谁。

例如定义如下Bird类:

class Bird:
    # 定义一个fly()方法
    def fly(self):
        print("正在执行fly方法")
    # 定义一个move()方法,move()方法需要借助fly()方法
    def move(self):
        # 使用self参数引用调用fly()方法的对象
        self.fly()
        print("正在执行move方法")

bird = Bird()
bird.move()

上面代码的move()方法中的self代表该方法的调用者,谁在调用move()方法,那么self就代表谁。因此该方法表示当一个Bird对象调用move()方法时,move()方法需要依赖它自己的 fly()方法。

在现实世界里,对象的一个方法依赖另一个方法的情形很常见,例如,吃饭方法依赖拿筷子或刀叉的方法,写程序方法依赖敲键盘方法,这种依赖都是同一个对象的两个方法之间的依赖。

当 Python对象的一个方法调用另一个方法时,不能省略self。也就是说,将上面的move方法改为如下形式是不正确的。

def move(self):
    # 省略self,下面的代码会报错
    fly()
    print("正在执行move方法")

此外,在构造方法中,self参数(第1个参数)代表该构造方法正在初始化的对象。例如如下代码。

class SelfInConstructor :
    def __init__(self) :
        # 在构造方法里定义一个name变量(局部变量)
        name = 'Bill'
        # 使用self代表该构造方法正在初始化的对象
        # 下面的代码将会把该构造方法正在初始化的对象的name实例变量设为Mike
        self.foo = 'Mike'
# 所有使用SelfInConstructor创建的对象的name实例变量将被设为Mike
print(SelfInConstructor().foo) # 输出Mike

在 SelfInConstructor的构造方法中,self参数总是引用该构造方法正在初始化的对象。程序中的代码将正在执行初始化的SelfInConstructor对象的name实例变量设为Mike,这意味着该构造方法返回的所有对象的name实例变量都等于Mike。

需要说明的是,自动绑定的self参数并不依赖具体的调用方式,不管是以方法调用还是以函数调用的方式执行它,self参数一样可以自动绑定。例如如下程序:

示例代码:self_demo.py

class Product:
    def process(self):
        print('self参数: ', self)
        
product = Product()
# 以方法形式调用process()方法
product.process() # <__main__.User object at 0x00000000021F8240
# 将User对象的test方法赋值给foo变量
process = product.process
# 通过process变量(函数形式)调用process()方法。process() # <__main__.User object at 0x00000000021F8240

上面程序中的代码以方法形式调用Product对象的 process方法,此时方法调用者当然会自动绑定到方法的第1个参数(self参数)。接下来以函数形式调用Product对象的process方法,看上去此时没有调用者了,但程序依然会把实际调用者绑定到process函数的第1个参数,因此上面程序的输出结果完全相同。

当self参数作为对象的默认引用时,程序可以像访问普通变量一样来访问这个self参数,甚至可以把self参数当成实例方法的返回值。看下面程序。

示例代码:return_self.py

class Person :
    def speed_up(self):
        if hasattr(self, 'speed'):
            self.speed += 1
        else:
            self.speed = 20
        # return self返回调用该方法的对象
        return self
person = Person()
# 可以连续调用同一个方法
person.speed_up().speed_up().speed_up().speed_up()
print("speed:", person.speed)

从上面程序中可以看出,如果在某个方法中把self参数作为返回值返回,则可以多次连续调用同一个方法,从而使得代码更加简洁。但是这种把self参数作为返回值的方法可能会造成实际意义的模

糊,例如上面的speed_up方法用于表示的速度的增加,也就是speed属性值加1,实际上不应该有返回值。也就是说,尽管使用self参数作为方法的返回值可以让代码更加简洁,但可能造成实际意义的模糊,所以这种方式要谨慎使用。

本文分享自微信公众号 - 极客起源(geekculture),作者:geekori

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 冠状病毒传播仿真器(Python版本)【附源代码】

    本文首先会解释一下到底什么是"冠状病毒",以及杀死"冠状病毒"的方法。然后会利用Python实现一个"冠状病毒"传播仿真器,来演示一下为何“不出门“ +“疯狂建...

    蒙娜丽宁
  • Python编程思想(26):成员变量

    李宁老师已经在「极客起源」 微信公众号推出《Python编程思想》电子书,囊括了Python的核心技术,以及Python的主要函数库的使用方法。读者可以在「极客...

    蒙娜丽宁
  • 靠!安装了macOS Catalina(10.15.4)后,文件系统都乱套了

    最近闲来无事,决定将我的两台apple电脑升级成最新的苹果系统(macOS Catalina),当然,由于以前升级过多次mac系统,所以毫不犹豫从app sto...

    蒙娜丽宁
  • 【leetcode刷题】T147-两数之和 IV - 输入 BST

    https://leetcode-cn.com/problems/two-sum-iv-input-is-a-bst

    木又AI帮
  • 强化学习第-1步

    function self = one_dimensional_env(len,fresh_time)

    万木逢春
  • iOS原生的搜索:UISearchController

    王大锤
  • PaddleX助力无人驾驶:基于YOLOv3的车辆检测和车道线分割实战

    无人驾驶汽车利用传感器技术、信号处理技术、通讯技术和计算机技术等,通过集成视觉、激光雷达、超声传感器、微波雷达、GPS、里程计、磁罗盘等多种车载传感器来辨识汽车...

    用户1386409
  • Airflow自定义插件, 使用datax抽数

    Airflow之所以受欢迎的一个重要因素就是它的插件机制。Python成熟类库可以很方便的引入各种插件。在我们实际工作中,必然会遇到官方的一些插件不足够满足需求...

    Ryan-Miao
  • Python的多态

    py3study
  • Django之频率组件

    写一个类,继承自SimpleRateThrottle,(根据ip限制)问:要根据用户现在怎么写:

    py3study

扫码关注云+社区

领取腾讯云代金券