访问控制
私有属性(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')
print(P1.age)
P1.growup(20) #正常范围
# P1.age=160 #超过正常范围,并绕过控制逻辑
print(P1.age)
私有属性
使用双下划线开头的属性名,就是私有属性,从外部无法访问该属性。
#私有属性
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')
# print(P1.__age)
P1.growup(20) #正常范围
# # P1.age=160 #超过正常范围,并绕过控制逻辑
# print(P1.__age) #访问不到
# P1.__age=58 #无法修改,__age未被覆盖 python解释器已为其改名_类名__变量名
print(P1.getage())
# print(P1.__dict__)
#直接修改私有变量
P1._Person__age=15
print(P1.getage())
print(P1.__dict__)
私有变量的本质:
类定义的时候,如果声明一个实例变量的时候,使用双下划线,python解释器会将其改名,转为:_类名__变量名,之前的名字就访问不到了。
知道私有变量的新名称,就可以直接从外部访问,并可以修改。
保护变量
在变量名前加一个下划线,称为保护变量。
_age属性未改变名称,和普通属性一样,解释器也未作任何特殊处理,只是开发者共同的约定,这种变量,如同私有变量,不要直接使用。
class Person:
def __init__(self,name,age=18):
self.name=name
self._age=age
tom = Person('tom')
print(tom._age)
print(tom.__dict__)
私有方法
参照保护变量、私有变量,使用单、双下划线命名的方法。
#私有方法
class Person:
def __init__(self,name,age=18):
self.name=name
self._age=age
def _getname(self):
return self.name
# def _getage(self):
# return self._age
def __getage(self):
return self._age
tom = Person("Tom")
print(tom._getname())
# print(tom._getage())
# print(tom.__getage()) #无此属性 改名:_Person__getage
print(tom.__dict__)
print(tom.__class__.__dict__)
# print(tom._Person__getage())
# print(tom.__dict__)
本质:
保护方法:单下划线的方法,只是开发者之间的约定,解释器不做任何改变。
私有方法:双下划线的方法,改名策略与私有变量相同:_类名__方法名
方法变量在类的__dict__中可以找到。
在python中使用单下划线或者双下划线来标识一个成员(即属性)被保护或被私有化隐藏起来。
但不管什么样的访问控制都不可能真正阻止用户修改,下划线只是一种提醒和警告,非必要不要修改被保护的成员。
属性装饰器
通过age和set_age操作属性
#通过age和set_age操作属性
class Person:
def __init__(self,name,age=18):
self.name=name
self.__age=age
def age(self): #与set方法结合用,必须先定义读取属性的方法
return self.__age
def set_age(self,age): #set方法设置属性,必须传参,变量名传入
self.__age=age
tom = Person("Tom")
# print(tom.__age) #直接读取不到
# print(tom.age())
# print(tom.__dict__)
# tom.__age=20 #私有属性,已改名,无法直接修改属性
# print(tom.age())
# print(tom.__dict__)
tom.set_age(20)
print(tom.age())
print(tom.__dict__)
使用属性装饰器@property
@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): #set方法设置属性,必须传参,变量名传入
self.__age=age
@age.deleter
def age(self):
# del self.__age
print("del")
tom = Person("Tom")
print(tom.age)
print(tom.__dict__)
tom.age = 20
print(tom.age)
print(tom.__dict__)
#del tom.age
注意:
使用@property装饰器时,三个方法要同名
@property装饰器:后面跟的函数名就是之后的属性名。它就是getter,必须要有的方法,只读属性
@setter装饰器:与属性名同名,且接收两个参数,第一个self,第二个是将要赋值的值,可写属性
@deleter装饰器:可以控制是否删除属性,很少用
@property装饰器必须在前,@setter、@deleter在后
#简单写法
# class Person:
# def __init__(self,name,age=18):
# self.name=name
# self.__age=age
#
# def getage(self):
# return self.__age
#
# def setage(self,age):
# self.__age=age
#
# def delage(self):
# del self.__age
#
# age=property(getage,setage,delage,'age property')
#
# tom = Person("Tom")
#
# print(tom.__dict__)
# print(tom.getage())
# print(tom.age)
# tom.age=20
# print(tom.age)
# print(tom.__dict__)
## tom.setage(30)
# print(tom.age)
# print(tom.__dict__)
本文介绍Python中私有属性的概念及实现方式,包括如何使用双下划线定义私有属性,以及如何通过属性装饰器实现对属性的访问控制。
3036

被折叠的 条评论
为什么被折叠?



