python高级编程函数_第二章:Python高级编程-魔法函数

笔记

2.1 什么是魔法函数(网络用语)

以双下划线开始,双下滑线结尾。魔法函数是为了增强一个类的特性。

魔法函数可以随意定义某个类的特性,这些方法在进行特定的操作时会自动被调用。

2.1.1 需求:封装一个员工列表,并遍历查看

(1)不使用魔法函数方法

#!usr/bin/env python

#-*- coding:utf-8 _*-

# __author__:lianhaifeng

# __time__:2020/5/10 18:20

class Company(object):

def __init__(self, employee_list):

self.employee = employee_list

company = Company(["tom", "bob", "jane"])

employee = company.employee

for em in employee:

print(em)

(2)使用__getitem__(self, item)魔法函数

#!usr/bin/env python

#-*- coding:utf-8 _*-

# __author__:lianhaifeng

# __time__:2020/5/10 18:20

class Company(object):

def __init__(self, employee_list):

self.employee = employee_list

def __getitem__(self, item):

return self.employee[item]

company = Company(["tom", "bob", "jane"])

for em in company:

print(em)

"""

在解释器执行到for语句时,解释器首先寻找对象的迭代器。

虽然company对象没有迭代器,

但是解释器会尝试去寻找__getitem__()这一魔法函数,

有了这个魔法函数的对象就是一个可迭代的类型,即便没有迭代器,

解释器会调用该魔法函数,直到其抛出异常结束。

若注释__getitem__代码片段,则会抛出不可迭代异常。

"""

注意:在案例中,魔法函数既不是属于,也不是从基继承过来。是一个独立的存在,往类里放入魔法函数之后,会增强类的一些类型。魔法函数不需要我们显示调用。Python会识别对象或自定义类的魔法函数,并隐式调用。

2.2 Python的数据模型以及数据模型对Python的影响

实际上魔法函数是网络上通常的叫法,其实魔法函数只不过是Python数据类型的一个概念而已。

"""

当实现了__getitem__(self, item)魔法函数,就可以使用for循环去遍历。魔法函数实际上会影响python语法的,或可以理解为Python语法实际上会识别一个对象或者说自定义类里的魔法函数。

"""

#-*- coding:utf-8 _*-

# __author__:lianhaifeng

# __time__:2020/5/10 18:20

# 使用__getitem__(self, item)魔法函数

class Company(object):

def __init__(self, employee_list):

self.employee = employee_list

def __getitem__(self, item):

return self.employee[item]

company = Company(["tom", "bob", "jane"]) # __getitem__(self, item) 实际上也是序列类型

company1 = company[:2]

print(company1)

"""

['tom', 'bob']

"""

如果不实现__getitem__(self, item)就会报错

#!usr/bin/env python

#-*- coding:utf-8 _*-

# __author__:lianhaifeng

# __time__:2020/5/10 18:20

class Company(object):

def __init__(self, employee_list):

self.employee = employee_list

# def __getitem__(self, item):

# return self.employee[item]

company = Company(["tom", "bob", "jane"])

company1 = company[:2]

print(company1)

"""

Traceback (most recent call last):

File "E:/projects/vue-django/myproject/sample/chapter02/company03.py", line 14, in

company1 = company[:2]

TypeError: 'Company' object is not subscriptable

"""

#!usr/bin/env python

#-*- coding:utf-8 _*-

# __author__:lianhaifeng

# __time__:2020/5/10 18:20

class Company(object):

def __init__(self, employee_list):

self.employee = employee_list

# def __getitem__(self, item):

# return self.employee[item]

company = Company(["tom", "bob", "jane"])

print(len(company)) # 没有定义__len__(self)或__getitem__(self, item)魔法函数时,这个语句会报错

"""

Traceback (most recent call last):

File "E:/projects/vue-django/myproject/sample/chapter02/company03.py", line 14, in

print(len(company))

TypeError: object of type 'Company' has no len()

"""

两种方式实现对象可len()

(1)getitem(self, item) + 切片 实现

(2)len(self, item) 实现

在调用内置函数len()时,解释器首先会调用魔法函数__len__(self),若没有,则退一步,去不断调用__getitem__(self, item)直到抛出异常,len()函数返回执行次数。

#!usr/bin/env python

#-*- coding:utf-8 _*-

# __author__:lianhaifeng

# __time__:2020/5/10 18:20

# 使用__getitem__(self, item)魔法函数 + 切片

class Company(object):

def __init__(self, employee_list):

self.employee = employee_list

def __getitem__(self, item):

return self.employee[item]

company = Company(["tom", "bob", "jane"])

company1 =company[:]

print(len(company1))

"""

3

"""

#!usr/bin/env python

#-*- coding:utf-8 _*-

# __author__:lianhaifeng

# __time__:2020/5/10 18:20

# 使用__len__(self)魔法函数

class Company(object):

def __init__(self, employee_list):

self.employee = employee_list

def __len__(self):

return len(self.employee)

company = Company(["tom", "bob", "jane"])

print(len(company))

"""

3

"""

魔法函数会影响Python语法和其内置函数本身的。

2.3 魔法函数一览

2.3.1 非数学运算

字符串表示 魔法函数提供了两个来应对开发模式的不同

(1)repr 用于命令行模式,作用:输入对象名即可调用repr方法# jupyter或ipython 命令行终端运行

class Company(object):

def __init__(self, employee_list):

self.employee = employee_list

def __repr__(self):

return ','.join(self.employee)

company = Company(['tom', 'bob', 'jane'])

company

"""

tom,bob,jane

"""

(2)__str__用于脚本,作用:print(对象名)即可调用str方法#!usr/bin/env python

#-*- coding:utf-8 _*-

# __author__:lianhaifeng

# __time__:2020/5/10 18:20

class Company(object):

def __init__(self, employee_list):

self.employee = employee_list

def __str__(self):

return ','.join(self.employee)

company = Company(['tom', 'bob', 'jane'])

print(company)

"""

tom,bob,jane

"""

"""

魔法函数只要定义了,就不需要开发者调用,Python解释器自己知道什么时候调用它。

"""

"""

集合、序列相关

__len__

__getitem__

__setitem__

__delitem__

__contains__

迭代相关

__iter__

__next__

可调用

__call__

with上下文管理器

__enter__

__exit__

数值转换

__abs__

__bool__

__int__

__float__

__hash__

__index__

元类相关

__new__

__init__

属性相关

__getattr__

__setattr__

__getattribute__

__setattribute__

__dir__

属性描述符

__get__

__set__

__delete__

协程

__await__

__aiter__

__anext__

__aenter__

__aexit

"""

2.3.2 数学运算

"""

数学运算在一般开发使用不多,在数据处理是用的比较多,这里简单举几个例子。

"""

# ============== __abs__ Demo start ============

class Nums(object):

def __init__(self, num):

self.num = num

def __abs__(self):

return abs(self.num)

num = Nums(-1)

print(abs(num)) # 结果:1

# ============== __abs__ Demo end ============

# ============== __add__ Demo start ============

class MyVector(object):

def __init__(self, x, y):

self.x = x

self.y = y

def __add__(self, other_instance):

re_vector = MyVector(self.x+other_instance.x, self.y+other_instance.y)

return re_vector

def __str__(self):

return "x:{x}, y:{y}".format(x=self.x, y=self.y)

first_vec = MyVector(1, 2)

second_vec = MyVector(2, 3)

print(first_vec+second_vec) # 结果:x:3,y:5

# ============== __add__ Demo end ============

一元运算符

__neg__ -

__pos__ +

__abs__ |x|

二元运算符

__lt__ <

__le__ <=

__eq__ ==

__ne__ !=

__gt__ >

__ge__ >=

算术运算符

__add__ +

__sub__ -

__mul__ *

__truediv__ /

__floordiv__ //

__mod__ %

__divmod__ divmod()

__pow__ ** 或 pow()

__round__ round()

反向算术运算符

__radd__

__rsub__

__rmul__

__rtruediv__

__rfloordiv__

__rmod__

__rdivmod__

__rpow__

增量赋值算术运算符

__iadd__

__isub__

__imul__

__itruediv__

__ifloordiv__

__imod__

__ipow__

位运算符

__invert__ ~

__lshift__ <<

__rshift__ >>

__and__ &

__or__ |

__xor__ ^

反向位运算符

__rlshift__

__rrshift__

__rand__

__rxor__

__ror__

增量赋值位运算符

__ilshift__

__irshift__

__iand__

__ixor__

__ior__

2.4 len函数的特殊性

len函数不仅仅调用__len__方法这么简单,len函数对于set dict list等Python原生数据结构做了内部的优化,其性能是非常高的。应为原生数据结构中,会有一个专门的字段来储存数据长度,那么len函数会直接去读取这个字段,而不会去遍历它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值