python进阶14:实例方法和类方法、types.MethodType()

本文介绍了Python面向对象编程的基础概念,包括实例方法、类方法及如何使用types.MethodType()动态添加方法到实例上。同时,文章详细解释了实例方法中私有属性的作用及访问方式,并通过示例展示了如何实现类方法。

1 实例方法

  一个实例的私有属性就是以__开头的属性,无法被外部访问,那这些属性定义有什么用?虽然私有属性无法从外

部访问,但是,从类的内部是可以访问的。除了可以定义实例的属性外,还可以定义实例的方法。实例的方法就是在

类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样

的:

class Person(object):

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

    def get_name(self):
        return self.name
  get_name(self) 就是一个实例方法,它的第一个参数是self。__init__(self, name)其实也可看做是一个特殊的

实例方法。调用实例方法必须在实例上调用:

>>> p1 = Person('Bob')
>>> print p1.get_name() #self不需要传入
Bob
  在实例方法内部,可以访问所有实例属性,这样,如果外部需要访问私有属性,可以通过方法调用获得,这种数

据封装的形式除了能保护内部数据一致性外,还可以简化外部调用的难度。

2 types.MethodType() 
  因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变

为一个方法:

import types
def fn_get_grade(self):
    if self.score >= 80:
        return 'A'
    if self.score >= 60:
        return 'B'
    return 'C'

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

  下面我们将fn_get_grade()方法添加到实例上:

>>> p1 = Person('Bob', 90)
>>> p1.get_grade = types.MethodType(fn_get_grade, p1, Person)
>>> print p1.get_grade()
A
>>> p2 = Person('Alice', 65)
>>> print p2.get_grade()
# ERROR: AttributeError: 'Person' object has no attribute 'get_grade'
  因p2实例没有绑定get_grade方法,所以出现错误。
3 定义类方法

  和属性类似,方法也分实例方法类方法

  在class中定义的全部是实例方法,实例方法第一个参数 self 是实例本身。定义类方法需要在方法前加上

@classmethod

class Person(object):
    count = 0
    @classmethod
    def how_many(cls):
        return cls.count
    def __init__(self, name):
        self.name = name
        Person.count = Person.count + 1

print Person.how_many()
p1 = Person('Bob')
print Person.how_many()
  通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本

身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count。因为是在类上调用,而非实例上调

用,因此类方法无法获得任何实例变量,只能获得类的引用。


Python中,类动态绑定属性方法允许在对象创建后为其添加属性方法,这体现了Python的动态特性。 ### 动态绑定属性 若只想给一个实例对象添加属性,那么就可以使用动态绑定属性的方法。为实例对象添加的属性,只适用于该对象使用。示例如下: ```python class Student: def __init__(self, name, age): self.name = name self.age = age stu1 = Student('张三', 20) stu2 = Student('李四', 21) # 为stu1动态添加属性 stu1.gender = "男" print(stu1.name, stu1.age, stu1.gender) # 输出: 张三 20 男 # print(stu2.name, stu2.age, stu2.gender) # 报错,对象里没有该属性 ``` 上述代码中,`gender`属性只绑定到了`stu1`实例对象上,`stu2`实例对象没有该属性,若尝试访问会引发`AttributeError`错误[^2]。 ### 动态绑定方法 同样,也可以在对象创建后为其动态绑定方法。示例如下: ```python class Student: def __init__(self, name, age): self.name = name self.age = age def study(self): print(f"{self.name}正在学习") stu1 = Student('张三', 20) # 动态绑定方法 from types import MethodType stu1.study = MethodType(study, stu1) stu1.study() # 输出: 张三正在学习 ``` 上述代码中,`study`方法被动态绑定到了`stu1`实例对象上,之后就可以像调用普通实例方法一样调用它。 ### `__dict__`属性与动态绑定 对于类来说,`__dict__`包含了类的静态函数、类函数、普通函数、全局变量以及一些内置的属性。而对于类的实例对象来说,`__dict__`则包含了与实例相关的属性及其值。动态绑定的属性方法也会反映在实例对象的`__dict__`属性中。示例如下: ```python class MyClass: class_var = 1 def __init__(self, instance_var): self.instance_var = instance_var obj = MyClass(10) print(MyClass.__dict__) # 类的__dict__属性 print(obj.__dict__) # 实例对象的__dict__属性 # 动态绑定属性 obj.new_attr = 20 print(obj.__dict__) # 包含了新绑定的属性 ``` 上述代码展示了类实例对象的`__dict__`属性,以及动态绑定属性后实例对象`__dict__`属性的变化[^3]。
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值