• python之特殊方法


    特殊方法的定义:

    1.定义在某些class当中

    2.不需要直接调用

    3.Python的某些函数或者是操作符会调用相应的特殊方法

    特殊方法很多,我们只需要编写用到的特殊方法,以及有关联性的特殊方法。

    ——————————————————————————————————————————

    __str__和__repr__方法
    如果要把一个类的实例变成 str,就需要实现特殊方法__str__():

    >>> 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)
    
        
    >>> p = Person('Bob','male')
    >>> print (p)
    (Person:Bob,male)

    但是当我们输入p的时候我们并不能显示出字符串

    >>> p
    <__main__.Person object at 0x035FC950>

    好像是__str__并没有调用

    因为 Python 定义了__str__()__repr__()两种方法,__str__()用于显示给用户,而__repr__()用于显示给开发人员。

    有一个偷懒的定义__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__
    
        
    >>> p = Person('Bob','Male')
    >>> p
    (Person:Bob,Male)

    这里我们在输入P的时候就不会显示出地址了。

    ————————————————————————————————————————————————

    __cmp__:
    对 intstr 等内置数据类型排序时,Python的 sorted() 按照默认的比较函数 cmp 排序,但是,如果对一组 Student 类的实例排序时,就必须提供我们自己的特殊方法 __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)]

    这里的是python2.0的写法,但是在python3.0当中,它的写法就不是这样的了。

    >>> 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 __lt__(self,s):
            return self.name < s.name
        def __gt__(self,s):
            return self.name > s.name
        def eg(self,s):
            return self.name == s.name
    
        
    >>> L = [Student('Tim',99),Student('Bob',88),Student('Alice',77)]
    >>> print (sorted(L))
    [(Alice:77), (Bob:88), (Tim:99)]

    ——————————————————————————————————————————————————

    __len__函数

    >>> class Student(object):
        def __init__(self,*args):
            self.names = args
        def __len__(self):
            return len(self.names)
    
        
    >>> L = Student('Bob','Alice','Tim')
    >>> print (len(L))
    3

    要让 len() 函数工作正常,类必须提供一个特殊方法__len__(),它返回元素的个数。

    ——————————————————————————————————————————————————

    数学运算

    Python 提供的基本数据类型 int、float 可以做整数和浮点的四则运算以及乘方等运算。

    但是,四则运算不局限于int和float,还可以是有理数、矩阵等。

    要表示有理数,可以用一个Rational类来表示:

    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 - self.q * r.p, 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):
            def mydiv(x,y):
                if x<y:
                    x,y=y,x
                while x%y!=0:
                    x,y=y,x%y
                    mydiv(x,y)
                return y
            r=mydiv(self.p,self.q)
            return '%s/%s' % (self.p/r,self.q/r)
    
        __repr__ = __str__
    
    r1 = Rational(1, 2)
    r2 = Rational(1, 4)
    print r1 + r2
    print r1 - r2
    print r1 * r2
    print r1 / r2

    ——————————————————————————————————————————————————

    类型转换

    为了能够将那个Rational函数变为int,我们可以使用int()

    在类里面我们可以使用特殊的函数转化。比如命名‘__int__()’

    >>> 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 self.p * 1.0 /self.q
    
        
    >>> print (float(Rational(7,2)))
    3.5
    >>> print (float(Rational(1,3)))
    0.3333333333333333

    __________________________________________________________________________

    @property

    当我们考虑隐秘性的时候,我们会使用__属性__来保证该属性,不会被外在所访问。

    class Student(object):
        def __init__(self, name, score):
            self.name = name
            self.__score = score
        def get_score(self):
            return self.__score
        def set_score(self, score):
            if score < 0 or score > 100:
                raise ValueError('invalid score')
            self.__score = score

    但是我们可以使用其他的方法来装饰函数,这样可以节约代码。

    >> 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
    
            
    >>> s = Student('Bob',59)
    >>> s.score = 60
    >>> print (s.score)
    60
    >>> s.score = 1000
    Traceback (most recent call last):
      File "<pyshell#17>", line 1, in <module>
        s.score = 1000
      File "<pyshell#13>", line 11, in score
        raise ValueError('invalid score')
    ValueError: invalid score

    第一个score(self)是get方法,用@property装饰,第二个score(self, score)是set方法,用@score.setter装饰,@score.setter是前一个@property装饰后的副产品。

    ——————————————————————————————————————————————————

    __slots__

    如果要限制添加的属性,例如,Student类只允许添加 name、genderscore 这3个属性,就可以利用Python的一个特殊的__slots__来实现。

    >>> class Student(object):
        __slots__ = ('name','gender','score')
        def __init__(self,name,gender,score):
            self.name = name
            self.gender = gender
            self.score = score
    
            
    >>> s = Student('Bob','male',59)
    >>> s.name = 'Tim'
    >>> s.score = 99
    >>> s.grade = 'A'
    Traceback (most recent call last):
      File "<pyshell#14>", line 1, in <module>
        s.grade = 'A'
    AttributeError: 'Student' object has no attribute 'grade'

    __slots__的目的是限制当前类所能拥有的属性,如果不需要添加任意动态的属性,使用__slots__也能节省内存。

    ——————————————————————————————————————————————————————

    __call__:

    一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__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 name is %s...'% friend)
    
        
    >>> p = Person('Bob','male')
    >>> p ('Tim')
    My name is Bob...
    My name is Tim...

    这里的就是将P变为了一个可调用对象。

  • 相关阅读:
    unity3d引擎中slua的使用
    分布式理论之一:Paxos算法的通俗理解
    ZIP压缩算法详细分析及解压实例解释
    MapReduce剖析笔记之八: Map输出数据的处理类MapOutputBuffer分析
    MapReduce剖析笔记之七:Child子进程处理Map和Reduce任务的主要流程
    MapReduce剖析笔记之六:TaskTracker初始化任务并启动JVM过程
    MapReduce剖析笔记之五:Map与Reduce任务分配过程
    MapReduce剖析笔记之四:TaskTracker通过心跳机制获取任务的流程
    Hadoop2.2.0安装过程记录
    序列化笔记之一:Google的Protocol Buffer格式分析
  • 原文地址:https://www.cnblogs.com/chang1203/p/5847490.html
Copyright © 2020-2023  润新知