Python随记(14) @property的使用 类和对象的BIF

一些与类和对象的BIF

1. issubclass(class,classinfo) 如果class是calssinfo的子类,返回true。 另外,一个类被认为是自身的子类,classinfo可以是类对象组成的元组,只要class是其中一个类的子类就是true。其他情况下,返回TypeError的异常。 # object是所有类的基类

2. ininstance(object,classinfo) object是class info的实例对象返回true 另外,如果object是class info的子类的实例对象,也符合条件。如果第一个参数不是对象,永远返回false。classinfo可以是类对象组成的元组,只要object是其中的子类,就返回true。如果第二个参数不是类或者类对象组成的元组,抛出异常。

3. hasattr(object,name)测试一个对象里是否有指定的属性,object就是对象,name属性名(属性的字符串名字)

class A:
	def __init__(self,x=1):
		self.x=x
a=A()
hasattr(a,'x')   #注意,属性名要用引号括起来
True

4. getattr(object,name,default)返回指定的属性值,如果指定的属性值不存在,返回default参数(可选)的值,没有设置default默认返回ArttributeError异常

5. setattr(object,name,value)设置对象中指定属性的值,如果指定属性不存在新建属性并赋值

6. delattr(object,name)删除指定的属性,属性不存在返回异常

7. property(fget=None,fset=None,fdel=None,doc=None) 通过属性设置属性。。。。

class C:
	def __init__(self, size = 10):
		self.size = size
	def getSize(self):
		return self.size
	def setSize(self, value):
		self.size = value
	def delSize(self):
		del self.size
	x = property(getSize, setSize, delSize)
c=C()
c.x    >>>10
c.x=12   c.x   >>>12
c.size   >>>12
del c.x    c.size  >>>AttributeError

property 的优势:举个例子,在上面这个例子中,这个程序慢慢写的很复杂了,有一天,你想把这个程序进行大改,把函数名进行改写,如果没有 property,那你提供给用户的调用接口就西药修改,就会降低用户体验,但是有了property,问题就不存在了,因为提供给用户的接口都是 x,程序里面无论如何修改,property里面的参数跟着改进行了,用户还是只用调用 x 来设置或者获取 size 属性就可以了。

@property的使用

官方的帮助文档(哪有帮助。。。)

 |  Decorators make defining new properties or modifying existing ones easy:
 |  
 |  class C(object):
 |      @property
 |      def x(self):
 |          "I am the 'x' property."
 |          return self._x
 |      @x.setter
 |      def x(self, value):
 |          self._x = value
 |      @x.deleter
 |      def x(self):
 |          del self._x

作用:将类的方法转换成类属性,可以用 对象。 直接获取属性值或者对属性赋值。通过property类实现(以后会在写的。。)也可以使用property装饰器来实现(多数情况)。使得我们调用属性的时候就会自动调用相应的方法,也就是增加一些额外的处理过程(例如类型检查或者验证)

廖老师的例子:

class Student(object):

    def get_score(self):
         return self._score

    def set_score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

调用时就要:

>>> s = Student()
>>> s.set_score(60) # ok!
>>> s.get_score()
60

相比于对属性的使用肯定是麻烦的,,,s.set_score(66)VSs.score = 66所以就可以使用@property

class Student(object):

    @property
    def score(self):
        return self._score   #得到一个内部属性

    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value
#就可以这样调用了:
s=Student()
s.score=66
s.score  >>>>66

score()+@property 就相当于 score=property(score) (装饰器嘛。。)用type打印<class 'property'>可见score已经是property的实例了。。。。(property类的实现,描述符以后在讲吧。。。。)

总之:@property将一个方法转换成一个属性,同时会创建@score.setter这个装饰器,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作。还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性。

class Student(object):

    @property
    def birth(self):              #可读写属性
        return self._birth

    @birth.setter
    def birth(self, value):
        self._birth = value

    @property
    def age(self):               #只读属性
        return 2015 - self._birth

就这??就这???然后我就找了很多文章了解这个语法糖的真正作用,,,,

在python中定义只读属性非@property莫属,如果细心留意大部分源码,都跑不了@property的身影。而定义只读属性也很简单:以需要定义的属性为方法名(上例age属性定义为方法),其上装饰内置装饰器@property就ok了。
  @property真正强大的是可以限制属性的定义。往往我们定义类,希望其中的属性必须符合实际,但因为在__init__里定义的属性可以随意的修改,导致很难实现。如我想实现Person类,规定每个人(即创建的实例)的年龄必须大于18岁,正常实现的话,则必须将属性age设为只读属性,然后通过方法来赋值,
(虽然一个意思但这个讲出来就有感觉。。。。)

以后的话我会在详细写一下property这个类的实现原理。。。。。。

另外python其实有三个内置修饰符的

staticmethod、classmethod 和 property,作用分别是把类中定义的实例方法变成静态方法、类方法和类属性。由于模块里可以定义函数,所以静态方法和类方法的用处并不是太多。


class Hello(object):
    def __init__:
        ...
 
@classmethod
def print_hello(cls):
    print("Hello")

classmethod 修饰过后,print_hello() 就变成了类方法,可以直接通过 Hello.print_hello() 调用,而无需绑定实例对象了

发布了25 篇原创文章 · 获赞 0 · 访问量 300

猜你喜欢

转载自blog.csdn.net/weixin_46192930/article/details/104959961