Python系列教程(四十):类的多种方法和属性访问控制

  一、类的多种方法介绍  

1、普通方法

    普通方法就是上一篇文章介绍的类的方法,它的第一个参数必然是self,由实例对象调用的方法,用的是最多也是这种方法。

2、类方法

    类方法,不同于普通方法,有一定的应用场景,具体有如下的特点:

    ① 类方法需要使用@classmethod装饰器装饰

    ② 类方法的第一个参数是cls,cls指示的是类对象自身

    ③ 通过类调用,会自动把类对象传入给cls,如果是对象调用,则会先找到所属的类,然后再传入给cls。

3、静态方法

    静态方法,跟self和cls都没有关系,也可以理解为跟类和实例对象都没有关系,可以看做是一个放在类中的普通函数,使用的比较少,具体有如下的特点:

    ① 静态方法需要使用@staticmethod装饰器装饰

    ② 静态方法没有要求第一个参数是self或者cls,不会隐式的传入参数

    ③ 可以通过类或者实例对象调用,静态方法只是一个声明在类中的普通方法,由类这个名词空间管理,其他毫无作用。

class Person:
    name = 'Wu Ming'
    
    #定义一个普通方法,第一个参数必须是self
    def method(self):
        self.name = 'Wei xiaobao'
        print(self.name)
    
    #定义一个类方法,第一个参数必须是cls
    @classmethod
    def class_method(cls):
        cls.name = 'Zhang Wuji'
        print(cls.name)
        
    #定义一个静态方法
    @staticmethod
    def static_method():
        print(Person.name)
        
>>> A = Person()

#调用类的方法,把A这个实例对象传入给self
>>> A.method()    
Wei xiaobao
>>> Person.method()
TypeError: method() missing 1 required positional argument: 'self'

#调用类方法,把Persion这个类对象传入给cls
>>> Person.class_method()
Zhang Wuji
>>> A.class_method()
Zhang Wuji

#调用类的静态方法,可以通过类或者实例对象调用静态方法
>>> Person.static_method()
Zhang Wuji
>>> A.static_method()
Zhang Wuji

    总结:

    ① 类的普通方法只能由类的实例对象调用,因为第一个参数self需要传入一个实例对象。

    ② 类的类方法和静态方法可以通过类或者实例对象调用,类方法的cls最终都只是接受一个类对象,静态方法不会自动隐式传入参数。

  二、属性的访问控制  

    类的第一特性就是封装,为了更好的保护内部代码,大多数情况不会直接暴露类中定义的代码,而是通过提供的接口进行调用,而为了避免在类的外部直接访问甚至是直接修改类的属性,Python提供了两种方法来控制类属性的访问。

1、私有属性

    在Python定义类属性的时候,使用双下划线“__”开头的属性,都是私有属性(私有变量和私有方法)。

class Person:
    def __init__(self, name, age):
        self.__name = name        #私有变量
        self.age = age
        self.__inner()
    
    def __inner(self):            #私有方法
        print(self.__name)
        print(self.age)
        
>>> A = Person('jimmy',29)        
jimmy
29
 
#在外部直接调用私有属性,抛出异常        
>>> A.__name      
AttributeError: 'Person' object has no attribute '__name'
>>> A.__inner()
AttributeError: 'Person' object has no attribute '__inner'

#在外部直接调用普通属性,正常访问
>>> A.age
29

    从上面的示例中可以看出,__name已经是私有属性,无法在外部访问了,而在内部可以正常使用。

    那么私有属性的本质是什么?  

    看一下实例对象和类对象的属性字典,你就明白了,对,它就是把属性名称改名了而已,仅此而已,所以你在外部无法直接使用原来的属性名称进行访问了。

>>> A.__dict__
{'_Person__name': 'jimmy', 'age': 29}

>>> Person.__dict__
'_Person__inner': <function __main__.Person.__inner(self)>,

    既然只是改了个名字,但是终究还是可以通过外部访问,那么我们是否可以访问或者修改呢?

>>> A._Person__name
'jimmy'

#通过实际属性名称修改__name变量的值
>>> A._Person__name = 'Jimmy'
>>> A.__dict__
{'_Person__name': 'Jimmy', 'age': 29}

#通过实际属性名称访问__inner方法
>>> A._Person__inner()
jimmy
29

    可以看到,我们仍然可以通过实际的属性名称去访问甚至是修改。

    私有属性的总结:

    ① 在属性名称前面加上双下划线“__”。

    ② 私有属性在外部无法直接访问和修改。

    ③ 私有属性的本质只是修改了属性名字,在原来的属性名字前面加上“_classname”,可以通过实际的名称进行访问和修改。

    ④ 私有属性不具备强制性,可以绕过限制,但是一般不会这么做。

2、保护属性

    在Python定义类属性的时候,使用一个下划线“_”开头的属性,就是保护属性。

    保护属性的访问控制强度还没有私有属性的高,连私有属性都可以绕过访问和修改,保护属性就更不要说限制了,这里的保护更多的是一种约定,因为保护属性和普通属性一样,只是说我用了保护属性,你在外部就不要随便访问和修改了。

  三、Python的方法重载  

    所谓方法重载,指的是同一个方法名,但是参数数量或者参数类型不一样,就是同一个方法的重载,在调用的时候,会根据传递的实参来自动调用相应的方法。

    而Python中没有方法重载,Python也不需要方法重载,因为我们在学习函数定义的时候,已经知道函数的形参是非常灵活的,可以实现多种不同的传参方式,已经满足方法重载的需求。

Jimmy's Blog ,版权所有丨如未注明,均为原创丨本网站采用BY-NC-SA协议进行授权,转载请注明转自:https://www.xjimmy.com/python-40-class2.html

Leave a Comment