魔法方法

魔法方法

  • 魔法方法总是被双下划线包围,例如__init__。
  • 魔法方法是面向对象的 Python 的一切,如果你不知道魔法方法,说明你还没能意识到面向对象的 Python 的强大。
  • 魔法方法的“魔力”体现在它们总能够在适当的时候被自动调用。
  • 魔法方法的第一个参数应为cls(类方法) 或者self(实例方法)。
    cls:代表一个类的名称
    self:代表一个实例对象的名称

基本的魔法方法

  • init(self[, …]) 构造器,当一个实例被创建的时候调用的初始化方法
class Re:
    def __init__(self,x,y):
        self.x=x
        self.y=y
    def c(self):
        return (self.x+self.y)*2
    def s(self):
        return self.x*self.y
r1=Re(3,4)
print(r1.c())#14
print(r1.s())#12

  • new(cls[, …]) 在一个对象实例化的时候所调用的第一个方法,在调用__init__初始化前,先调用__new__。
    1.new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由 Python 解释器自动提供,后面的参数直接传递给__init
    2.new__对当前类进行了实例化,并将实例返回,传给__init__的self。但是,执行了__new,并不一定会进入__init__,只有__new__返回了,当前类cls的实例,当前类的__init__才会进入。
class A(object):
    def __init__(self, value):
        print("into A __init__")
        print(self.value)
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into A __new__")
        print(cls)
        return object.__new__(cls)


class B(A):
    def __init__(self, value):
        print("into B __init__")
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into B __new__")
        print(cls)
        return super().__new__(cls, *args, **kwargs)
b = B(13)
#into B __new__
<class '__main__.B'>
into A __new__
<class '__main__.B'>
into B __init__
class A(object):
    def __init__(self, value):
        print("into A __init__")
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into A __new__")
        print(cls)
        return object.__new__(cls)


class B(A):
    def __init__(self, value):
        print("into B __init__")
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into B __new__")
        print(cls)
        return super().__new__(A, *args, **kwargs)  # 改动了cls变为A


b = B(10)

# into B __new__
# <class '__main__.B'>
# into A __new__
# <class '__main__.A'>

-若__new__没有正确返回当前类cls的实例,那__init__是不会被调用的,即使是父类的实例也不行,将没有__init__被调用。

例:(利用__new__实现单例模式。)

class A:
    pass
x=A()
y=A()
print(id(x),id(y))#1825303356272 1825303764752
class A:
    __temp=None
    def __new__(cls):
        if cls.__temp is None:
            cls.__temp=object.__new__(cls)
            return cls.__temp
        else:
            return cls.__temp
x=A()
y=A()
print(id(x),id(y))#1825303764032 1825303764032
  • __new__方法主要是当你继承一些不可变的 class 时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。
class Exchange(str):
    def __new__(cls,string):
        string=string.lower()
        return str.__new__(cls,string)
x=Exchange("I LOVE PYTHON")
print(x)
#i love python

-str(self):
1.当你打印一个对象的时候,触发__str__
2.当你使用%s格式化的时候,触发__str__
3.str强转数据类型的时候,触发__str__

  • repr(self):
    1.repr是str的备胎
    2.有__str__的时候执行__str__,没有实现__str__的时候,执行__repr__
    3.repr(obj)内置函数对应的结果是__repr__的返回值
    4.当你使用%r格式化的时候 触发__repr__
class Dog:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __str__(self):
        return "name is {0},age is {1}.".format(self.name,self.age)
    def __repr__(self):
        return "dog:{0},age:{1}".format(self.name,self.age)
    def eat(self):
        print("{0} is eating...".format(self.name))
    def drink(self):
        print("{0} is drinking...".format(self.name))
keke=Dog("Keke",4)
print(keke)
print(str(keke))
print(repr(keke))
keke.eat()
#name is Keke,age is 4.
#name is Keke,age is 4.
#dog:Keke,age:4
#Keke is eating...

<注>
str(self) 的返回结果可读性强。也就是说,str 的意义是得到便于人们阅读的信息,就像下面的 ‘2019-10-11’ 一样。

repr(self) 的返回结果应更准确。怎么说,repr 存在的目的在于调试,便于开发者使用。

import datetime

today = datetime.date.today()
print(str(today))  
print(repr(today)) 
print('%s' %today)  
print('%r' %today)  
#2020-08-05
#datetime.date(2020, 8, 5)
#2020-08-05
#datetime.date(2020, 8, 5)

算术运算符

  • add(self, other)定义加法的行为:+
  • sub(self, other)定义减法的行为:-
class Locat:
    def __init__(self,x,y):
        self.x=x
        self.y=y
    def __add__(self,others):
        return Locat(self.x+others.x,self.y+others.y)
    def __sub__(self,others):
        return Locat(self.x-others.x,self.y-others.y)
    def prt(self):
        print("location:x={0},y={1}".format(self.x,self.y))
def myfunction():
    a=Locat(x=1,y=2)
    a.prt()
    b=Locat(x=3,y=4)
    b.prt()
    c=a-b
    c.prt()
if __name__=='__main__':
    myfunction()
#location:x=1,y=2
#location:x=3,y=4
#location:x=-2,y=-2        

类似的:
mul(self, other)定义乘法的行为:*
truediv(self, other)定义真除法的行为:/
floordiv(self, other)定义整数除法的行为://
mod(self, other) 定义取模算法的行为:%
divmod(self, other)定义当被 divmod() 调用时的行为
divmod(a, b)把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)。

 print(divmod(9,4))
#(2, 1)

反算术运算符

反运算魔方方法,与算术运算符保持一一对应,不同之处就是反运算的魔法方法多了一个“r”。当文件左操作不支持相应的操作时被调用。
在这里插入图片描述

增量赋值运算符

  • iadd(self, other)定义赋值加法的行为:+=
  • isub(self, other)定义赋值减法的行为:-=
  • imul(self, other)定义赋值乘法的行为:*=
  • itruediv(self, other)定义赋值真除法的行为:/=
  • ifloordiv(self, other)定义赋值整数除法的行为://=
  • imod(self, other)定义赋值取模算法的行为:%=
  • ipow(self, other[, modulo])定义赋值幂运算的行为:**=
  • ilshift(self, other)定义赋值按位左移位的行为:<<=
  • irshift(self, other)定义赋值按位右移位的行为:>>=
  • iand(self, other)定义赋值按位与操作的行为:&=
  • ixor(self, other)定义赋值按位异或操作的行为:^=
  • ior(self, other)定义赋值按位或操作的行为:|=

一元运算符

  • neg(self)定义正号的行为:+x
  • pos(self)定义负号的行为:-x
  • abs(self)定义当被abs()调用时的行为
  • invert(self)定义按位求反的行为:~x

属性访问

  • getattr(self, name): 定义当用户试图获取一个不存在的属性时的行为。
  • getattribute(self, name):定义当该类的属性被访问时的行为(先调用该方法,查看是否存在该属性,若不存在,接着去调用__getattr__)。
  • setattr(self, name, value):定义当一个属性被设置时的行为。
  • delattr(self, name):定义当一个属性被删除时的行为。
class A:
    def __gettattribute__(self,item):
        print("__gettattribute__")
        return super().__getattribute__(item)
    def __getattr__(self,item):
        print("__getattr__")
    def __setattr__(self,key,value):
        print("__setattr__")
        super().__setattr__(key,value)
    def __delattr__(self, item):
        print('__delattr__')
        super().__delattr__(item)
        
a=A()
a.x
#__getattr__
a.x=1
#__setattr__
del a.x
#__delattr__

描述符

描述符就是将某种特殊类型的类的实例指派给另一个类的属性。

  • get(self, instance, owner)用于访问属性,它返回属性的值。
  • set(self, instance, value)将在属性分配操作中调用,不返回任何内容。
  • del(self, instance)控制删除操作,不返回任何内容。
class MyDecriptor:
    def __get__(self, instance, owner):
        print('__get__', self, instance, owner)

    def __set__(self, instance, value):
        print('__set__', self, instance, value)

    def __delete__(self, instance):
        print('__delete__', self, instance)


class Test:
    x = MyDecriptor()


t = Test()
t.x #__get__ <__main__.MyDecriptor object at 0x000002196985E370> <__main__.Test object at 0x00000219698C1F10> <class '__main__.Test'>
t.x = 'x-man' #__set__ <__main__.MyDecriptor object at 0x000002196985E370> <__main__.Test object at 0x00000219698C1F10> x-man
del t.x #__delete__ <__main__.MyDecriptor object at 0x000002196985E370> <__main__.Test object at 0x00000219698C1F10>

迭代器

  • 是访问集合元素的一种方式
  • 迭代器是一个可以记住遍历的位置的对象。
  • 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。
  • 迭代器只能往前不会后退。
  • 字符串,列表或元组对象都可用于创建迭代器:
d={1:"a",2:"b",3:"c"}
for each in d:
    print("{0}->{1}".format(each,d[each]))
#1->a
#2->b
#3->c

1.迭代器有两个基本的方法:iter() 和 next()。
2.iter(object) 函数用来生成迭代器。
3.next(iterator[, default]) 返回迭代器的下一个项目。
4.iterator – 可迭代对象
5.default – 可选,用于设置在没有下一个元素时返回该默认值,如果不6.设置,又没有下一个元素则会触发 StopIteration 异常。

links = {1: 'a', 2: 'b', 3: 'c'}
it = iter(links)
print(next(it))  #1
print(next(it))  #2
print(next(it))  #3
print(next(it))  #StopIteration


把一个类作为一个迭代器使用需要在类中实现两个魔法方法 iter() 与 next() 。

iter(self)定义当迭代容器中的元素的行为,返回一个特殊的迭代器对象, 这个迭代器对象实现了 next() 方法并通过 StopIteration 异常标识迭代的完成。
next() 返回下一个迭代器对象。
StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 next() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。

生成器

1.在 Python 中,使用了 yield 的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器
2.在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
3.调用一个生成器函数,返回的是一个迭代器对象。

def myGen():
    print('生成器执行!')
    yield 1
    yield 2


myG = myGen()
print(next(myG))  
# 生成器执行!
# 1

print(next(myG))  # 2
print(next(myG))  # StopIteration
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

colaj_49485675

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值