python学习_三

2020.04.29
限制动态添加属性

如果在类定义时,在类中添加了一个类级别的属性(也就是属性添加在与方法同级),并且这个属性命名有特殊的规定,只能为:slots
具体使用方法如下:

class s(object):
    __slots__ = ('name','age')
    //something else

此时如果在代码中想要给给类的实例添加不在__slots__中的属性/方法名,虽然在添加时不会报错,但是实际上并没有添加上,后续再访问的该动态添加的属性时就会报错:

has no attribute

但是,__slots__属性只对定义它的类有效,对于其子类无效。
但是很奇怪的是,在python中,如果子类和父类都定义了__slots__属性。那么子类中的__slots__是子类与父类__slots__的并集。


限制动态添加属性的值的范围
需要使用到装饰器decorator的@property标签,具体使用方法如下:
//假设想给一个类添加一个score属性,并且限制该属性在0-100范围内

class s(object):
    #首先使用property标签标注在与想要添加的属性名相同的方法上,该方法相当于一个setter方法
    @property
    def score(self):
        return self._score    #注意这里一定要这样定义属性,带上前缀单下划线。不然会重复调用
    #然后使用配套的setter标签,用法如下
    @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")    #限制值的范围

如果只定义了setter而没有定义getter标签(只有property没有.setter)。那么该属性只读。


如果一个类中定义的属性或者方法名开头和结尾都是有双下划线“__”,在python中这样的属性或方法是具备特殊作用的。
比如上面提到的__slots__属性,用于限制实例动态绑定的属性。
同样,在定义的每个类中的__init__函数(如果有。但是如果没有就继承父类的),这个函数相当于override构造函数。
接下来学习其他类似__init__函数:
①__str__函数
一般而言,str函数在python中用于将传入的参数转为字符串,并且如果直接输出一个实例的名字,实际上也会自动调用这个函数,此时如果定义的类中没有override str()函数(也就是没有定义__str__方法),此时一般会返回类名+地址。
而如果此时想要在调用实例名字的时候,输出我们想要其返回的信息如当前的属性信息等,就可以在该类中定义函数名为__str__的函数,重写str函数,如下:

class s(object):
    def __str__(self):
        #返回想要的信息
        return some information

-此时再调用该类的实例名就会返回想要返回的信息。

tips:
在python中还有一个repr()函数,用法与str函数一样,主要用于调试。同样可以在类中重写该方法,重写的方法一样,不过也可以用一个小技巧:
在重写的__str__方法后,在与定义方法同级的位置使用:
repr = str
语句

②__iter__函数
从名字可以看出,这是迭代器方法。
也就是说,如果一个类实现了该方法,这个就可以被迭代,也就是可以用在for循环中(数字是不行的)。
根据java的使用经验,迭代器一般都有一个next()方法,python中同样,这两个方法配套使用。
具体使用如下:
//使用斐波那契数列函数

class fib(object):
    def __init__(self):
        self.a, self.b = 0  #定义初始值
    def __iter__(self):
        return self   #返回迭代的本身
    def __next__(self):
        self.a,self.b = self.b,self.a+self.b   #斐波那契计算公式
        if self.a > 100000:  #设置循环次数
            raise StopIteration()
        return self.a  #返回下一个值

-此时就可以直接在for循环中使用该类:

for iter in fib():
     print(iter)

-会打印一系列斐波那契数列直至循环条件再结束。

③__getitem__
该函数主要用于按下标取元素,就像列表、元组那样。
如果一个类重写该方法,该类中的元素就可以按下标取出。
依然以斐波那契为例:
#这里只写出该方法而不全部再写该类

def __getitem__(self, n):
        a, b = 1, 1
        for x in range(n):
            a, b = b, a + b
        return a

④__getattr__函数
该函数主要用于对属性的查询。
对于没有重写该方法的类,如果其实例要查询一个不存在属性,此时就会报错。当重写该方法后,就可以进一步的动态添加查询的属性。使用如下:

class r(object):
    def __init__(self,n):
        self.name = n
    def __getattr__(self,attr):
        if attr == 'score':
            return 111
        raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)

上面的代码表示,现在该类的实例拥有一个必定存在的name属性,仅此而已。
此时定义的__getattr__函数体表示:
如果查询的属性是score属性,那么此时就动态的追加调用者实例score属性,并赋值111。
如果不是score则抛出异常。
这样使得程序健壮性更好。

⑤__call__函数
定义该函数的类,可以像调用函数那样调用自身,具体如下:

class Student(object):
    def __init__(self, name):
        self.name = name

    def __call__(self):
        print('My name is %s.' % self.name)
-
>>>s = Student("sss")
>>>s()
My name is sss.
-

可以看到,Student类的实例像调用函数那样调用自身:s()。
此时Student可以被称为一个callable对象,也就是可调用对象。
可以使用callable()函数查询:

>>>callable(Student)
true
>>>callable(str)
false
callable([])
false
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值