1方法重载

1.1 Python不支持方法重载

在强类型语言(比如:C语言、Java语言)中,可以定义多个重名的方法,只要保证方法的签名唯一即可。方法签名包含三个部分:

  • 方法名
  • 参数数目
  • 参数类型

Python中,方法的参数没有声明类型(调用时才能确定参数的类型),参数的数目也可以由可变参数控制。因此,python中没有方法的重载。定义一个方法既可以有多种调用方式,相当于实现了其他语言中的方法的重载。

但是这种方式,相对强类型语言,可能没有那么直观,因为要在一个函数里面处理多种情况。

如果我们在类体中定义了多个重名的方法,只有最后一个方法有效

建议:不要使用重名的方法

1.2 代码说明

示例代码:

class Person:

    def say_hi(self):
        print("hello")

    def say_hi(self, name):
        print("{0},hello".format(name))


p1 = Person()
p1.say_hi("niefajun")
print("--" * 20)
p1.say_hi()

运行结果:

niefajun,hello
----------------------------------------
Traceback (most recent call last):
  File "test.py", line 13, in <module>
    p1.say_hi()
TypeError: say_hi() missing 1 required positional argument: 'name'

程序说明:
在类Person定义了两个方法,但是两个方法同名,都是say_hi,按照前面的解释,只有最后一个生效,那么就等效于只定义了say_hi(self, name)这一个方法。第一次采用p1.say_hi("niefajun")这种方式调用,和参数能够对应,所以可以正常输出内容。第二次采用p1.say_hi(),没有参数,相当于缺少一个参数,所以提示错误信息:TypeError: say_hi() missing 1 required positional argument: 'name'

2方法的动态性

python是动态语言,我们可以动态的为类添加新的方法,或者动态的修改类的已有的方法。

2.1代码说明

示例代码:

# 定义一个独立的普通方法
def play_game(self):
    print("玩游戏休息一会")


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

    def work(self):
        print("努力工作")


Person.play = play_game
p1 = Person("p1")
p1.work()
p1.play()

运行结果:

努力工作
玩游戏休息一会

程序说明:
对象p1是类Person的实例,虽然在Person类声明中只定义了work一个方法,但是后面通过动态赋值的方法,增加了一个play属性,指向函数play_game,实际就是增加了一个play的实例方法。所以后面执行p1.work()p1.play()都能输出正确的结果。

说明:虽然通过方法动态性可以动态的添加方法,但是在实际开发中不建议这样做,这样会导致代码可读性下降,存在潜在风险。

3.__slots__类变量限制动态性

Python中可以很方便的实现属性、方法的动态性,使用起来很方便,但是也会造成一定的不确定性,所以在Python中使用__slots__属性来限制属性和方法动态性。

示例代码:

class Person:
    """使用__slots__限制Person只允许添加name一个属性"""
    __slots__ = ('name',)

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

p1 = Person("聂发俊")
print(p1.name)
print("--" * 20)

p1.age = 100
print(p1.age)

运行结果:

聂发俊
----------------------------------------
Traceback (most recent call last):
  File "test.py", line 12, in <module>
    p1.age = 100
AttributeError: 'Person' object has no attribute 'age'

程序说明:
在定义Person类的时候,使用了__slots__属性,限定属性只有name一个字段,不允许动态添加其他字段。程序运行,前面正常实例化对象p1,并打印p1.name属性,结果是正常的。后面动态复制age属性为100,因为__slots__的限定,无法动态添加属性,所以提示错误信息:AttributeError: 'Person' object has no attribute 'age'.


备注:
更多精彩博客,请访问:聂发俊的技术博客
对应视频教程,请访问:python400
完整markdown笔记,请访问: python400_learn_github