关于Python中property装饰器及访问权限问题全解!!

python中property装饰器中的getter和setter详解 及访问权限性问题全解:

部分内容转载自网络:
添加链接描述

1.一个类中绑定的属性,当为私有属性时,当类被实例化为对象时,可以通过类中的方法调用私有属性,代码例:

class Student(object):
	"""docstring for Student"""
	def __init__(self, name,age,tel):
		self.__name = name
		self.age = age
		self.tel = tel

	def play(self):
		print(self.__name,self.age,self.tel)

	def test(self):
		print(self.__name)
		
def main():
	student = Student('张三',18,123)
	student.play()
	student.test()

if __name__ == '__main__':
	main()

CMD:
张三 18 123
张三

2.通过自定义get,set方法,调用方法的形式去对私有属性进行操作

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.__age = age
 
    #定义对私有属性的get方法,获取私有属性
    def getAge(self):
        return self.__age
 
    #定义对私有属性的重新赋值的set方法,重置私有属性
    def setAge(self,age):
        self.__age = age
 
person1 = Person("tom",19)
person1.setAge(20)
print(person1.name,person1.getAge())  #tom 2

3.通过调用property属性对set,get方法进行了封装。然后操作私有属性

class Student(object):
    def __init__(self, name, age):
        self.name = name
        self.__age = age
 
    #定义对私有属性的get方法,获取私有属性
    def getAge(self):
        return self.__age
 
    #定义对私有属性的重新赋值的set方法,重置私有属性
    def setAge(self,age):
        self.__age = age
 
    p = property(getAge,setAge) #注意里面getAge,setAge不能带()
 
s1 = Student("jack",22)
s1.p = 23 #如果使用=,则会判断为赋值,调用setAge方法。
print(s1.name,s1.p)  #jack 23   ,直接使用s1.p会自动判断会取值,调用getAge

尖叫提示:

property方法中有个四个参数 第一个参数是方法名,调用 对象.属性 时自动触发执行方法,对应下面的getter方法 第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法,对应下面的setter方法 第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法,对应下面的deleter方法 第四个参数是字符串,调用 对象.属性.doc ,此参数是该属性的描述信息

4.直接使用property标注同名函数的形式。这是最终开发中常用的方法。

#3.上面两种还是太麻烦,直接使用property标注同名函数的形式。这是最终开发中常用的方法。
class Teacher(object):
    def __init__(self, name, age,speak):
        self.name = name
        self.__age = age
        self.__speak = speak
 
 
    @property      #注意1.@proterty下面默认跟的是get方法,如果设置成set会报错。
    def age(self):
        return self.__age
 
    @age.setter    #注意2.这里是使用的上面函数名.setter,不是property.setter.
    def age(self,age):
        if age > 150 and age <=0:  #还可以在setter方法里增加判断条件
            print("年龄输入有误")
        else:
            self.__age = age
 
    @property
    def for_speak(self):  #注意2.这个同名函数名可以自定义名称,一般都是默认使用属性名。
        return self.__speak
 
    @for_speak.setter
    def for_speak(self, speak):
        self.__speak = speak
 
t1 = Teacher("herry",45,"Chinese")
t1.age = 38    #注意4.有了property后,直接使用t1.age,而不是t1.age()方法了。
t1.for_speak = "English"  
print(t1.name,t1.age,t1.for_speak)  #herry 38 English

4.property中的@property和@name.setter方法(即getter和setter方法)必须同时使用,否则会出现 NameError: name ‘name’ is not defined和AttributeError: can’t set attribute错误

尖叫提示:

1.@property成为属性函数,可以对属性赋值时做必要的检查,比如在setter方法里加过滤判断条件。此外相比自定义的get和set方法,property保证了代码的短小精悍,对私有属性的操作代码格式化模块化。
2.@property只有一个参数self,且要有返回值,所以一般定义属性的get方法。 3.注意@property调用方式,没有括号,而是直接调用属性名即可。

5.name.deleter 方法,注意,deleter方法需要先有getter和setter方法后才能正常使用

class Student(object):
	"""docstring for Student"""
	def __init__(self, name,age,tel):
		self.__name = name
		self.age = age
		self.tel = tel

	@property
	def name(self):
		return self.__name

	@name.setter
	def name(self,name):
		self.__name = name

	@name.deleter
	def name(self):
		print('name.deleter')
		del self.__name

	#p = property(getname,setname)

	def play(self):
		print(self.__name,self.age,self.tel)

	def test(self):
		print(self.__name)

		
def main():
	student = Student('张三',18,123)
	student.play()
	student.test()
	#student.setname('李四')
	#print(student.age,student.getname())
	student.name = '李四'
	print(student.name,student.age,student.tel)
	del student.name    #属性已经删除
	print(student.name)	 
"""
CMD:
张三 18 123
张三
李四 18 123
name.deleter
Traceback (most recent call last):
  File "test.py", line 49, in 
    main()
  File "test.py", line 46, in main
    print(student.name)
  File "test.py", line 17, in name
    return self.__name
AttributeError: 'Student' object has no attribute '_Student__name'
"""
if __name__ == '__main__':
	main()

6.property对方法的使用

1.@property 装饰方法时,可以将方法当成类的属性的形式进行调用,操作方法如果操作实例属性一样。
2.python中的类有经典类和新式类,新式类的property属性比经典类的property属性丰富。( 如果该类继object,那么该类是新式类 ),但是在Python 3.x中取消了经典类,默认都是新式类,并且不必显式的继承object,所以如果是使用python3则不存在这个问题了。如果是python2新式类和经典类property所带的方法数量是不一样的。

尖叫提示:

1.经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法
2.新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
3.由于新式类中具有三种访问方式,我们可以根据它们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除


class Goods(object):
 
    def __init__(self):
        # 原价
        self.original_price = 100
        # 折扣
        self.discount = 0.8
 
    @property
    def price(self):
        # 实际价格 = 原价 * 折扣
        new_price = self.original_price * self.discount
        return new_price
 
    @price.setter
    def price(self, value):
        self.original_price = value  #在这里修改原来类属性original_price
 
    @price.deleter  #注意这个deleter修饰器生效的前提是在该方法体内增加了del删除属性的操作,属性才会真的被删除。
    def price(self):
        del self.original_price  #这个才是实际删除属性的操作。
obj = Goods()
print(obj.price)         # 获取商品价格,80
obj.price = 200   # 修改商品原价,160
print(obj.price)   #160
print(obj.original_price) #200
del obj.price     # 删除商品原价,这里original_price属性被删除了,所以下面调用会报错。
print(obj.price)  #AttributeError: 'Goods' object has no attribute 'original_price'

你可能感兴趣的:(python)