面向对象-访问控制

私有(private)属性

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


    def growup(self, i=1):
        if i > 0 and i < 150:
            self.age += i


p1 = Person('tom')
p1.growup(20)
p1.growup(160)
print(p1.age)

输出为:

38

上例,本来想通过方法控制属性,但是由于属性在外部可以访问,或者说可见,就可以直接绕过方法,直接修改这个属性

python提供了私有属性可以解决这个问题

私有属性

使用双下划线开头的属性名,就是私有属性

示例:

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


    def growup(self, i=1):
        if i > 0 and i < 150:
            self.__age += i


p1 = Person('tom')
p1.growup(20)
p1.growup(160)
print(p1.__age)

输出为:

Traceback (most recent call last):
  File "E:/PycharmProjects/untitled/test/a.py", line 23, in <module>
    print(p1.__age)
AttributeError: 'Person' object has no attribute '__age'

外部访问不到__age,age没有定义,也访问不到

可以使用方法来访问__age

示例:

扫描二维码关注公众号,回复: 3378611 查看本文章
class Person:
    def __init__(self, name, age=18):
        self.name = name
        self.__age = age


    def growup(self, i=1):
        if i > 0 and i < 150:
            self.__age += i


    def getage(self):
        return self.__age


p1 = Person('tom')
p1.growup(20)
p1.growup(160)
print(p1.getage())

输出为:

38

私有变量的本质

类定义的时候,如果声明一个实例变量的时候,使用双下划线,python解释器会将其改名,转换名称为_类名——变量名的名称,所以用原来的名字访问不到了

直接修改私有变量

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


    def growup(self, i=1):
        if i > 0 and i < 150:
            self.__age += i


    def getage(self):
        return self.__age


p1 = Person('tom')
p1.growup(20)

p1._Person__age = 15
print(p1.__dict__)
print(p1.getage())

输出为:

{'name': 'tom', '_Person__age': 15}
15

从上例可以看出,知道了私有变量的名称,就可以直接从外部访问到并修改他

保护变量

在变量名前使用一个下划线,称为保护变量

示例:

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


tom = Person('tom')
print(tom.__dict__)
print(tom._age)

输出为:

{'name': 'tom', '_age': 18}
18

_age属性根本就没有改变名称,和普通的属性一样,解释器不做任何特殊处理

这只是开发者共同的约定,看见这种变量,就如同私有变量,不要直接使用

私有方法

参照保护变量,私有变量,使用单下划线,双下划线命名方法

私有方法的本质

单下划线的方法只是开发者之间的约定,解释器不做任何改变

双下划线的方法,是私有方法,解释器会改名,改名策略和私有变量相同,_类名_方法名

方法变量都在类的__dict__中可以找到

属性装饰器

一般好的设计师,把实例的属性保护起来,不让外部直接访问,外部使用getter读取属性和setter方法设置属性

示例:

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


    def age(self):
        return self.__age


    def set_age(self,age):
        self.__age = age


tom = Person('tom')
print(tom.age())
tom.set_age(30)
print(tom.age())

输出为:

18
30

通过age'和set_age方法操作属性

python提供了属性property装饰器

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


    @property
    def age(self):
        return self.__age


    @age.setter
    def age(self,age):
        self.__age = age

    @age.deleter
    def age(self):
        print('del')


tom = Person('tom')
print(tom.age)
tom.age = 30
print(tom.age)
del tom.age

property装饰器

后面跟的函数名就是以后的属性名,他就是getter,必须有,有了它至少是只读属性

setter装饰器

与属性名同名,且接收2个参数,第一个是self,第二个是将要复制的值,有了它属性可写

deleter装饰器

可以控制是否删除属性,很少用

property装饰器必须在前,setter,deleter装饰器在后

property装饰器能通过简单的方法,把对方法的操作变成对属性的访问,并起到了一定隐藏效果

对象的销毁

类中可以定义__del__方法,称为析构函数(方法)

销毁类的实例的时候调用,以释放占用的资源,其中就放些清理资源的代码,比如释放连接

注意这个方法不能引起对象的真正销毁,只是对象销毁的时候会自动调用

使用del语句删除实例,引用计数减1,当引用计数为0时,会自动调用__del__方法

由于python实现了垃圾回收机制,不能确定对象何时执行垃圾回收

由于垃圾回收对象销毁时,才会真正清理对象,还会在回收对象之前自动调用__del__方法,除非你明确知道自己的目的,建议不要手动调用这个方法

方法重载(overload)

其他面向对象的高级语言中,会有重载的概念。

所谓重载,就是同一个方法名,但参数数量,类型不一样,就是同一个方法的重载

python没有重载,不需要重载,python中,方法定义中,形参非常灵活,不需要指定类型,参数个数也不固定,一个函数的定义可以实现很多种不同形式实参的调用,所以python不需要方法重载

封装

将数据和操作组织到类中,即属性和方法

将数据隐藏起来,给使用者提供操作,使用者通过操作就可以获取或者修改数据getter和setter

通过访问控制,暴露适当的数据和操作给用户,该隐藏的隐藏起来,例如保护成员或虽有成员

猜你喜欢

转载自www.cnblogs.com/rivendare/p/9713415.html