zoukankan      html  css  js  c++  java
  • Python定制类

    Python的特殊方法

    • 特殊方法定义在class中
    • 不需要直接调用
    • Python的某些函数或操作符会调用对应的特殊方法

    python中 __str__和__repr__

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

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

    python中 __cmp__

    对 int、str 等内置数据类型排序时,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.score < s.score:
                return 1
            elif self.score > s.score:
                return -1
            else:
                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', 99)]
    print sorted(L)

    上述 Student 类实现了__cmp__()方法,__cmp__用实例自身self和传入的实例 s 进行比较,如果 self 应该排在前面,就返回 -1,如果 s 应该排在前面,就返回1,如果两者相当,返回 0。

    python中 __len__

    如果一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。

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

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

    class Fib(object):
        def __init__(self, num):
            self.num = num
            self.fibo = [0, 1]
            i = 2
            while i < self.num:
                self.fibo.append(self.fibo[i - 2] + self.fibo[i - 1])
                i = i + 1
    
        def __str__(self):
            return str(self.fibo)
    
        def __len__(self):
            return len(self.fibo)
    
    
    f = Fib(10)
    print f
    print len(f)
    #输出
    [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
    10

    python中 @property

    因为Python支持高阶函数,在函数式编程中我们介绍了装饰器函数,可以用装饰器函数把 get/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

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

    >>> s = Student('Bob', 59)
    >>> s.score = 60
    >>> print s.score
    60
    >>> s.score = 1000
    Traceback (most recent call last):
      ...
    ValueError: invalid score

    例子二:

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

    请给Student类加一个grade属性,根据 score 计算 A(>=80)、B、C(<60)。

    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
    
        @score.getter
        def grade(self):
            if self.score>=80:
                return 'A'
            elif self.score<60:
                return 'C'
            else:
                return 'B'
    
    s = Student('Bob', 59)
    print s.grade
    
    s.score = 60
    print s.grade
    
    s.score = 99
    print s.grade

    python中 __slots__

    由于Python是动态语言,任何实例在运行期都可以动态地添加属性。

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

    class Student(object):
        __slots__ = ('name', 'gender', 'score') #__slots__是指一个类允许的属性列表:
        def __init__(self, name, gender, score):
            self.name = name
            self.gender = gender
            self.score = score
    >>> 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'

    例子2:

    假设Person类通过__slots__定义了name和gender,请在派生类Student中通过__slots__继续添加score的定义,使Student类可以实现name、gender和score 3个属性。

    class Person(object):
    
        __slots__ = ('name', 'gender')
    
        def __init__(self, name, gender):
            self.name = name
            self.gender = gender
    
    class Student(Person):
    
        __slots__ = ('score')
    
        def __init__(self, name, gender, score):
            super(Student, self).__init__(name,gender)
            self.score = score
    
    s = Student('Bob', 'male', 59)
    s.name = 'Tim'
    s.score = 99
    print s.score
  • 相关阅读:
    基于摸板匹配的目標跟蹤算法
    spoj 2713 Can you answer these queries IV
    zoj 3633 Alice's present
    hdu 3642 Get The Treasury
    poj 1195 Mobile phones
    poj 2760 End of Windless Days
    zoj 3540 Adding New Machine
    spoj 1716 Can you answer these queries III
    spoj 1043 Can you answer these queries I
    spoj 2916 Can you answer these queries V
  • 原文地址:https://www.cnblogs.com/dear_diary/p/6890046.html
Copyright © 2011-2022 走看看