Python 中的特殊方法(定制类):__str__、__cmp__、__len__、数学运算、类型转换、@property运用、__slots__和__call__函数

Python中的特殊方法

Python的特殊方法定义在 class中,不需要直接进行显示调用,Python的某些操作符或者函数会自动调用对应的特殊方法。这些方法如:__str__()__len__()__cmp__()等。下面这些更全面:
Python中的特殊方法
正确实现特殊方法:首先只需要编写用到的特殊方法;其次有关联性的特殊方法必须都实现,如编写了特殊方法 __getattr__(),那么特殊方法 __setattr__()__delattr__()也必须实现。

__str____repr__方法:

先来看代码示例:

class Person(object):

    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

class Student(Person):

    def __init__(self, name, gender, score):
        super(Student, self).__init__(name, gender)
        self.score = score

    def __str__(self):
        return '(Student: %s, %s, %s)' % (self.name, self.gender, self.score)
    
    __repr__ = __str__

s = Student('Bob', 'male', 88)
print s            # 输出结果为:(Student: Bob, male, 88)

__str__()方法用来把一个类变成一个字符串输出,在 class中定义该方法,可以使类按照我们想要的格式进行输出。__str__()用于显示给用户,而__repr__()用于显示给开发人员。

__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):         # 定义__cmp__()方法
        if self.name < s.name:    # 比较规则(和默认比较规则相同)
            return -1
        elif self.name > s.name:
            return 1
        else:
            return 0

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

L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 77)]
print sorted(L)   # [(Alice: 77), (Bob: 88), (Tim: 99)]  按照姓名排序

升级版本:先判断类型,然后按照分数排序,分数相同按照姓名排序。如下:

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 not isinstance(s, Student):
            return -1
        else:
            return -cmp(self.score, s.score) or cmp(self.name, s.name)

L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 99)]
print sorted(L)      # 结果为:[(Alice: 99), (Tim: 99), (Bob: 88)]

注意:在 Python3.4.3版本之后,已经没有cmp() 函数了。被 operator模块中的一系列函数取代,并且使用时需要导入,如下:

import operator

a, b = 'Hello', 'name'
operator.lt(a, b)       # 小于比较
operator.le(a, b)       # 小于等于比较
operator.eq(a, b)       # 等于比较
operator.ne(a, b)       # 不等于比较
operator.gt(a, b)       # 大于比较
operator.ge(a, b)       # 大于等于比较

# 可在类中编写的内置函数如下:
operator.__lt__(a, b)       # 小于比较
operator.__le__(a, b)       # 小于等于比较
operator.__eq__(a, b)       # 等于比较
operator.__ne__(a, b)       # 不等于比较
operator.__gt__(a, b)       # 大于比较
operator.__ge__(a, b)       # 大于等于比较
__len__()函数:

如果一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。要让 len() 函数工作正常,类必须提供一个特殊方法__len__(),它返回元素的个数。代码示例如下:

class Fib(object):
    def __init__(self, num):
        a, b, l= 0, 1, []
        for item in range(int(num)):
            l.append(a)
            a, b = b, a+b
        self.nums = l
    def __len__(self):
        return len(self.nums)
    def __str__(self):
        return str(self.nums)

f = Fib(10)
print f          # 输出结果为:[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
print len(f)     # 输出结果为:10
Python 中的数学运算

Python 提供的基本数据类型 int、float 可以做整数和浮点的四则运算以及乘方等运算。但是,四则运算不局限于int和float,还可以是有理数、矩阵等

通过定制类,计算有理数(分数形式)的加减乘除四则运算。分别编写__add__()__sub__()__mul__()__div__()函数。代码示例如下:

def gcd(a, b):
    return gcd(b, a%b) if b!=0 else a

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):
        temp = gcd(self.p, self.q)
        return '%s/%s' % (self.p/temp, self.q/temp)

    __repr__ = __str__

r1 = Rational(1, 2)
r2 = Rational(1, 4)
print r1 + r2         # 3/4
print r1 - r2         # 1/4
print r1 * r2         # 1/8
print r1 / r2         # 2/1
Python中的类型转换

Rational类实现了有理数运算,还可以实现int()float()类型转换,示例如下:

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 int(Rational(1, 3))      # 0
Python中@property运用:

Python支持高阶函数,在函数式编程中我们介绍了装饰器函数,可以用装饰器函数把设置和获取属性的 get/set 方法“装饰”成属性调用:

class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.__score = score
    @property 
    def score(self):            # 实现 get()方法
        return self.__score

    @score.setter
    def score(self, score):     # 实现 set()方法
        if score < 0 or score > 100:
            raise ValueError('invalid score')
        self.__score = score

    @property
    def grade(self):            # 实现 grade属性的 get()方法
        if self.__score < 60: return 'C'
        elif self.__score <80: return 'B'
        else: return 'A'

s = Student('Bob', 59)
print s.grade               # 输出为:C

s.score = 99                # 输出为:A
print s.grade

s = Student('Bob', 59)
s.score = 60
print s.score      # 60
s.score = 1000
"""
Traceback (most recent call last):
  ...
ValueError: invalid score
"""
Python中限制属性函数__slots__():

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

class Person(object):

    __slots__ = ('name', 'gender')

    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

class Student(Person):

    __slots__ = ('score')         # 实际上允许的属性还有从父类继承来的 'name' 和 'gender'

    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   # 99
Python中对类调用函数__call__():

在Python中,函数其实是一个对象,所有的函数都是可调用对象。

一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()

class Fib(object):
    def __call__(self, num):
        a, b, l= 0, 1, []
        for item in range(int(num)):
            l.append(a)
            a, b = b, a+b
        return l

f = Fib()       # 获取类对象
print f(10)     # 像调用函数一样,调用类
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
The `functools.cmp_to_key` function is a utility function in Python's `functools` module that helps convert a comparison function to a key function. In Python, sorting a list of objects requires a way to compare the objects. This is done by providing a comparison function that takes two objects as input and returns `-1`, `0`, or `1` depending on whether the first object is less than, equal to, or greater than the second object. However, some sorting functions in Python (such as the `sorted` function) require a key function instead of a comparison function. A key function takes a single object as input and returns a value that can be used for sorting. The `cmp_to_key` function helps convert a comparison function to a key function by returning a new function that takes a single object as input and returns a tuple `(comparison_result, object)` where `comparison_result` is the result of calling the original comparison function with the input object and another object, and `object` is the input object itself. This tuple can then be used for sorting. Here's an example of how to use `cmp_to_key`: ``` from functools import cmp_to_key def compare_length(str1, str2): if len(str1) < len(str2): return -1 elif len(str1) > len(str2): return 1 else: return 0 strings = ['cat', 'dog', 'elephant', 'a', 'zebra'] sorted_strings = sorted(strings, key=cmp_to_key(compare_length)) print(sorted_strings) # Output: ['a', 'cat', 'dog', 'zebra', 'elephant'] ``` In this example, we define a comparison function `compare_length` that compares the lengths of two strings. We then use `cmp_to_key` to convert this comparison function to a key function, and pass it to the `sorted` function to sort a list of strings by length. The resulting sorted list is `['a', 'cat', 'dog', 'zebra', 'elephant']`.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值