Python 定制类 特殊方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 定制类 特殊方法相关的知识,希望对你有一定的参考价值。

1、特殊方法

定义在class中

不需要直接调用,python的某些函数或操作符会自动的调用对应的特殊方法。

如定义了person类,使用print p 语句打印person类的实例时,就调用了特殊方法__str__()

此时就需要在person类中实现这个方法。

使用特殊方法时注意:

只需要编写用到的特殊方法

有关联性的特殊方法都必须实现(如__getattr__,__setattr__,delattr__)

2、python中 __str__和__repr__

__str__()用于显示给用户,而__repr__()用于显示给开发人员。

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
    def __str__(self):
        return ‘(Person: %s, %s)‘ % (self.name, self.gender)
    __repr__ = __str__ #直接让repr和str相同

定义了repr函数后,在调试时直接向命令行输入p即可输出person的信息,否则会输出

<__main__.Person object at 0x0000000002E66C88>

__str__和__repr__函数会被子类继承。

3、python中 __cmp__

为了对对象进行排序,可以使用函数sorted函数,前提是设置了类的__cmp__方法。

class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score
    def __str__(self):
        return ‘(%s: %s)‘ % (self.name, self.score)
    __repr__ = __str__

    def __cmp__(self, s):
        if self.name < s.name:
            return -1
        elif self.name > s.name:
            return 1
        else:
            return 0
 
>>> L = [Student(‘Tim‘, 99), Student(‘Bob‘, 88), Student(‘Alice‘, 77)]
>>> print sorted(L)
[(Alice: 77), (Bob: 88), (Tim: 99)]
 

4、python中 __len__

调用len()返回实例的长度.

class Students(object):
    def __init__(self, *args):
        self.names = args
    def __len__(self):
        return len(self.names)
 
>>> ss = Students(‘Bob‘, ‘Alice‘, ‘Tim‘)
>>> print len(ss)
3
任务:

斐波那契数列是由 0, 1, 1, 2, 3, 5, 8...构成。

请编写一个Fib类,Fib(10)表示数列的前10个元素,print Fib(10) 可以打印出数列的前 10 个元素,len(Fib(10))可以正确返回数列的个数10。

代码1:(参考代码)

可以使用str()将整型列表转化为字符串。

class Fib(object):
    def __init__(self, num):
        a, b, L = 0, 1, []
        for n in range(num):
            L.append(a)
            a, b = b, a + b
        self.numbers = L

    def __str__(self):
        return str(self.numbers)

    __repr__ = __str__

    def __len__(self):
        return len(self.numbers)

f = Fib(10)
print f
print len(f)

代码2:(自己写的)
class Fib(object):

    def __init__(self, num):
        self.num = num
        
    def __str__(self):
        if(self.num==1):
            return "[0]"
        elif(self.num==2):
            return "[0,1]"
        else:
            fib_str = "[0,"
            fib=[0,1]
            for k in range(2,self.num+1):
                fib_str = fib_str+ str(fib[k-1]) + ","
                fib.append(fib[k-1]+fib[k-2])
            return fib_str[:-1]+‘]‘
    def __len__(self):
        return self.num   

f = Fib(10)
print f
print len(f)

5、python中数学运算(运算符重载)

例:有理数可以用p/q表示,其中p和q都是整数。

调用求最大公约数的gcd函数(递归):

欧几里得定理:若a=b*r+q,则 GCD(a,b)=GCD(b,q)

def gcd(a,b):
    if(b==0):
        return a
    return gcd(b,a%b)
class Rational(object):
    def __init__(self, p, q):
        self.p = p
        self.q = q

    def __add__(self, r):
        return Rational(self.p * r.q + self.q * r.p, self.q * r.q)

    def __sub__(self, r):
        return Rational(self.p*r.q-r.p*self.q,self.q*r.q)

    def __mul__(self, r):
        return Rational(self.p*r.p,self.q*r.q)

    def __div__(self, r):
        return Rational(self.p*r.q,self.q*r.p)

    def __str__(self):
        g = gcd(self.p,self.q)
        return ‘%s/%s‘ % (self.p/g, self.q/g)

    __repr__ = __str__

r1 = Rational(1, 2)
r2 = Rational(1, 4)
print r1 + r2
print r1 - r2
print r1 * r2
print r1 / r2

6、python中类型转换

__int__ 和 __float__方法实现类型转换,
__str__ 方法也可以看做是一种类型转换。
class Rational(object):
    def __init__(self, p, q):
        self.p = p
        self.q = q

    def __int__(self):
        return self.p // self.q

    def __float__(self):
        return float(self.p)/float(self.q)

print float(Rational(7, 2))
print float(Rational(1, 3))

7、python中 @property(装饰器函改写set和get方法)

@property 修饰方法后即是get方法。

“@+方法名字+点+setter”是个固定格式与@property搭配使用,set方法。

如果没有定义set方法,就不能对“属性”赋值,这时,就可以创建一个只读“属性”。

 
class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.__score = score
    @property
    def score(self):
        return self.__score
    @score.setter
    def score(self, score):
        if score < 0 or score > 100:
            raise ValueError(‘invalid score‘)
        self.__score = score

8、python中 __slots__ 属性限制

__slots__规定了一个类允许的属性列表。不允许添加列表外的属性。

class Student(object):
    __slots__ = (‘name‘, ‘gender‘, ‘score‘)
    def __init__(self, name, gender, score):
        self.name = name
        self.gender = gender
        self.score = score
强行添加grade属性会报错。
>>> s = Student(‘Bob‘, ‘male‘, 59)
>>> s.name = ‘Tim‘ # OK
>>> s.score = 99 # OK
>>> s.grade = ‘A‘
Traceback (most recent call last):
  ...
AttributeError: ‘Student‘ object has no attribute ‘grade‘

9、python中__call__  把类实例变成可调用对象

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

    def __call__(self, friend):
        print ‘My name is %s...‘ % self.name
        print ‘My friend is %s...‘ % friend
 
>>> p = Person(‘Bob‘, ‘male‘)
>>> p(‘Tim‘)
My name is Bob...
My friend is Tim...
 
第四节的斐波那契数列问题,可以改用call实现。
class Fib(object):
        
    def __call__(self,num):
        a=0
        b=1
        L=[]
   
        for n in range(1,num+1):
            L.append(a)
  
            temp = b
            
            b = a + b
            a = temp
      
        return L
            
f = Fib()
print f(10)
 
参考代码:
class Fib(object):
    def __call__(self, num):
        a, b, L = 0, 1, []
        for n in range(num):
            L.append(a)
            a, b = b, a + b
        return L

f = Fib()
print f(10)

注意代码中 高亮语句,使用参考代码的写法,就省去了一个中间变量。

 



















以上是关于Python 定制类 特殊方法的主要内容,如果未能解决你的问题,请参考以下文章

python元编程之使用动态属性实现定制类--特殊方法__setattr__,__getattribute__篇

python学习之运用特殊方法,定制类

python进阶-- 04 如何定制类

python 面向对象九 定制类

Python学习之定制类

python定制类