python 魔法方法总结
一、__str__
改变对象的字符串显示,可以理解为print打印对象的显示
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    # 定义对象的字符串表示
    def __str__(self):
        return self.name
s1 = Student('张三', 24)
print(s1)  # 会调用s1的__str__方法
>>> 张三
二、__repr__
在python解释器环境下,会默认显示对象的repr表示。
>>> class Student:
...     def __init__(self, name, age):
...         self.name = name
...         self.age = age
...     def __repr__(self):
...         return self.name
...
>>> s1 = Student('张三', 24)
>>> s1
张三
总结:
str函数或者print函数调用的是obj.str()
repr函数或者交互式解释器调用的是obj.repr()
注意:
如果__str__没有被定义,那么就会使用__repr__来代替输出。
__str__和__repr__方法的返回值都必须是字符串。
三、__format__
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    __format_dict = {
        'n-a': '名字是:{obj.name}-年龄是:{obj.age}',  # 名字是:lqz-年龄是:18
        'n:a': '名字是:{obj.name}:年龄是:{obj.age}',  # 名字是:lqz:年龄是:18
        'n/a': '名字是:{obj.name}/年龄是:{obj.age}',  # 名字是:/年龄是:18
    }
    def __format__(self, format_spec):
        if not format_spec or format_spec not in self.__format_dict:
            format_spec = 'n-a'
        fmt = self.__format_dict[format_spec]
        print(fmt) #{obj.name}:{obj.age}
        return fmt.format(obj=self)
s1 = Student('lqz', 24)
ret = format(s1, 'n/a')
print(ret)  # lqz/24
四、__del__
当对象的内存被施放的时候执行
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
class A:
    def __del__(self):
        print('删除了...')
a = A()
print(a)  # <__main__.A object at 0x10164fb00>
del a  # 删除了...
print(a)  # NameError: name 'a' is not defined
五、__dict__和__slots__
Python中的类,都会从object里继承一个__dict__属性,这个属性中存放着类的属性和方法对应的键值对。一个类实例化之后,这个类的实例也具有这么一个__dict__属性。但是二者并不相同。
class A:
    some = 1
    def __init__(self, num):
        self.num = num
a = A(10)
print(a.__dict__)  # {'num': 10}
a.age = 10
print(a.__dict__)  # {'num': 10, 'age': 10}
从上面的例子可以看出来,实例只保存实例的属性和方法,类的属性和方法它是不保存的。正是由于类和实例有__dict__属性,所以类和实例可以在运行过程动态添加属性和方法。
但是由于每实例化一个类都要分配一个__dict__变量,容易浪费内存。因此在Python中有一个内置的__slots__属性。当一个类设置了__slots__属性后,这个类的__dict__属性就不存在了(同理,该类的实例也不存在__dict__属性),如此一来,设置了__slots__属性的类的属性,只能是预先设定好的。
当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的小型数组来构建的,而不是为每个实例都定义一个__dict__字典,在__slots__中列出的属性名在内部被映射到这个数组的特定索引上。使用__slots__带来的副作用是我们没有办法给实例添加任何新的属性了。
注意:尽管__slots__看起来是个非常有用的特性,但是除非你十分确切的知道要使用它,否则尽量不要使用它。比如定义了__slots__属性的类就不支持多继承。__slots__通常都是作为一种优化工具来使用。--摘自《Python Cookbook》8.4
注意事项:
slots__的很多特性都依赖于普通的基于字典的实现。
另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。大多数情况下,你应该只在那些经常被使用到的用作数据结构的类上定义__slots,比如在程序中需要创建某个类的几百万个实例对象 。
关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。它更多的是用来作为一个内存优化工具。
六、__item__、__attr__系列
class Foo:
    def __init__(self, name):
        self.name = name
    def __getitem__(self, item):
        print(self.__dict__[item])
    def __setitem__(self, key, value):
        print('obj[key]=lqz赋值时,执行我')
        self.__dict__[key] = value
    def __delitem__(self, key):
        print('del obj[key]时,执行我')
        self.__dict__.pop(key)
    def __delattr__(self, item):
        print('del obj.key时,执行我')
        self.__dict__.pop(item)
    def __setattr__(self,key,value):
        print('obj.key = value的时候执行我')
        self.__dict__[key] = value
    def __getattr__(self,item):
        print('obj.get(key)的时候执行我')
        return self[item]
f1 = Foo('sb')
print(f1.__dict__)
f1['age'] = 18
f1.hobby = '泡妞'
del f1.hobby
del f1['age']
f1['name'] = 'lqz'
print(f1.__dict__)
七、__init__
使用Python写面向对象的代码的时候我们都会习惯性写一个 init 方法,init 方法通常用在初始化一个类实例的时候。例如:
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __str__(self):
        return '<Person: {}({})>'.format(self.name, self.age)
p1 = Person('张三', 24)
print(p1)
上面是__init__最普通的用法了。但是__init__其实不是实例化一个类的时候第一个被调用的方法。当使用 Persion(name, age) 来实例化一个类时,最先被调用的方法其实是 new 方法。
八、__new__
其实__init__是在类实例被创建之后调用的,它完成的是类实例的初始化操作,而 __new__方法正是创建这个类实例的方法
class Person:
    def __new__(cls, *args, **kwargs):
        print('调用__new__,创建类实例')
        return super().__new__(Person)
    def __init__(self, name, age):
        print('调用__init__,初始化实例')
        self.name = name
        self.age = age
    def __str__(self):
        return '<Person: {}({})>'.format(self.name, self.age)
p1 = Person('张三', 24)
print(p1)
输出:
调用__new__,创建类实例
调用__init__,初始化实例
<Person: 张三(24)>
__new__方法在类定义中不是必须写的,如果没定义的话默认会调用object.__new__去创建一个对象(因为创建类的时候默认继承的就是object)。
如果我们在类中定义了__new__方法,就是重写了默认的__new__方法,我们可以借此自定义创建对象的行为。
举个例子:
重写类的__new__方法来实现单例模式。
class Singleton:
    # 重写__new__方法,实现每一次实例化的时候,返回同一个instance对象
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            cls._instance = super().__new__(Singleton)
        return cls._instance
    def __init__(self, name, age):
        self.name = name
        self.age = age
s1 = Singleton('张三', 24)
s2 = Singleton('李四', 20)
print(s1, s2)  # 这两实例都一样
print(s1.name, s2.name)
九、__call__
call 方法的执行是由对象后加括号触发的,即:对象()。拥有此方法的对象可以像函数一样被调用。
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __call__(self, *args, **kwargs):
        print('调用对象的__call__方法')
a = Person('张三', 24)  # 类Person可调用
a()  # 对象a可以调用
注意:
new、init、__call__等方法都不是必须写的。
十、__doc__
定义类的描述信息(注释)
class A:
    """我是A类的描述信息"""
    pass
print(A.__doc__)
十一、__iter__和__next__
如果一个对象拥有了__iter__和__next__方法,那这个对象就是迭代器
class A:
    def __init__(self, start, stop=None):
        if not stop:
            start, stop = 0, start
        self.start = start
        self.stop = stop
    def __iter__(self):
        return self
    def __next__(self):
        if self.start >= self.stop:
            raise StopIteration
        n = self.start
        self.start += 1
        return n
a = A(1, 5)
from collections import Iterator
print(isinstance(a, Iterator))
for i in A(1, 5):
    print(i)
for i in A(5):
    print(i)
aaa=A(1)
print(next(aaa))
print(next(aaa)) #抛异常
十二、__enter__和__exit__
一个对象如果实现了__enter__和___exit__方法,那么这个对象就支持上下文管理协议,即with语句
class A:
    def __enter__(self):
        print('进入with语句块时执行此方法,此方法如果有返回值会赋值给as声明的变量')
        return 'oo'
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('退出with代码块时执行此方法')
        print('1', exc_type)
        print('2', exc_val)
        print('3', exc_tb)
with A() as f:
    print('进入with语句块')
    # with语句中代码块出现异常,则with后的代码都无法执行。
    # raise AttributeError('sb')
    print(f) #f打印出oo
print('嘿嘿嘿')
十三、__len__
拥有__len__方法的对象支持len(obj)操作。
class A:
    def __init__(self):
        self.x = 1
        self.y = 2
    def __len__(self):
        return len(self.__dict__)
a = A()
print(len(a))
十四、__hash__
拥有__hash__方法的对象支持hash(obj)操作。
class A:
    def __init__(self):
        self.x = 1
        self.x = 2
    def __hash__(self):
        return hash(str(self.x) + str(self.x))
a = A()
print(hash(a))
十五、__eq__
拥有__eq__方法的对象支持相等的比较操作
class A:
    def __init__(self,x,y):
        self.x = x
        self.y = y
    def __eq__(self,obj):
        # 打印出比较的第二个对象的x值
        print(obj.x)
        if self.x +self.y == obj.x+obj.y:
            return True
        else:
            return False
a = A(1,2)
b = A(2,1)
print(a == b)
python 魔法方法总结的更多相关文章
- Python魔法方法总结及注意事项
		1.何为魔法方法: Python中,一定要区分开函数和方法的含义: 1.函数:类外部定义的,跟类没有直接关系的:形式: def func(*argv): 2.方法:class内部定义的函数(对象的方法 ... 
- python魔法方法:__getattr__,__setattr__,__getattribute__
		python魔法方法:__getattr__,__setattr__,__getattribute__ 难得有时间看看书....静下心来好好的看了看Python..其实他真的没有自己最开始想的那么简单 ... 
- python魔法方法大全
		1.python魔法方法详解: python魔法方法是可以修改重载的,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而 ... 
- python 魔法方法补充(__setattr__,__getattr__,__getattribute__)
		python 魔法方法补充 1 getattribute (print(ob.name) -- obj.func())当访问对象的属性或者是方法的时候触发 class F(object): def _ ... 
- 1. Python 魔法方法
		Python 魔法方法 基础: 如果你想... 所以,你写... Python调用... 初始化一个实例 x = MyClass() x.__init__() 作为一个字符串的"官方&quo ... 
- with上下文管理  python魔法方法
		with语法在Python里很常见, 主要的利好是使用代码更简洁. 常见的使用场景有: 1. 资源对象的获取与释放. 使用with可以简化try...finally ... 2. 在不修改函数代码的前 ... 
- python 魔法方法诠释
		什么是Python魔法方法 什么是魔法方法呢?它们在面向对象的Python的处处皆是.它们是一些可以让你对类添加"魔法"的特殊方法. 它们经常是两个下划线包围来命名的(比如 ini ... 
- python 魔法方法
		I am not a creator, I just a porter. Note: Everything is object in python. 对于Python来说一切都是对象,也就是函数的参数 ... 
- python 魔法方法之:__getitem__ __setitem__ __delitem__
		h2 { color: #fff; background-color: #7CCD7C; padding: 3px; margin: 10px 0px } h3 { color: #fff; back ... 
- python 魔法方法(学习过程的笔记)
		有小伙伴会问,什么是python的魔法方法,python的魔法方法有什么用呢, 它们在面向对象的Python的处处皆是.它们是一些可以让你对类添加"魔法"的特殊方法. 它们经常是两 ... 
随机推荐
- Python常用推导式
			列表推导式: #列表推导式 #基本格式[] # 变量 = [for循环的变量 for循环一个可迭代对象] # 变量 = [i for i in 可迭代对象 if 条件] 条件为true才进行appen ... 
- 03.Java的前世今生
			C&C++ 1972年C诞生 ◆贴近硬件,运行极快,效率极高. ◆操作系统,编译器,数据库,网络系统等 ◆指针和内存管理 1982年C++诞生 ◆面向对象 ◆兼容C ◆图形领域.游戏等 背景 ... 
- MySQL触发器的详细教学与综合分析
			所有知识体系文章,GitHub已收录,欢迎老板们前来Star! GitHub地址: https://github.com/Ziphtracks/JavaLearningmanual MySQL触发器 ... 
- @uoj - 310@ 【UNR #2】黎明前的巧克力
			目录 @description@ @solution@ @accepted code@ @details@ @description@ Evan 和 Lyra 都是聪明可爱的孩子,两年前,Evan 开 ... 
- loads和dumps的用法
			import json s='{"name":"wuxie","sex":"m","data":nu ... 
- LaTeX中常用代码段snippets(持续更新)
			1.displaymath 单行数学环境,不带编号. \begin{displaymath} This\ is\ displaymath\ envirment.\ I\ don 't\ have\ a ... 
- 提交代码到gitbub.com
			提交代码到gitbub.com touch README.md //新建说明文件 git init //在当前项目目录中生成本地git管理,并建立一个隐藏.git目录 git add . //添加当前 ... 
- 【解读】TCP三次握手和四次挥手
			TCP有6种标识: 1.SYN(建立连接) 2.ACK(确认) 3.PSH(传送) 4.FIN(结束) 5.RST(重置) 6.URG(紧急) 一.TCP三次握手 第一次握手(发送:连接请求 ... 
- MongoDB入门二
			MongoDB配置 本地启动 c:\MongoDB\bin>mongod.exe --dbpath "C:\\MongoDB\data\db" --logpath " ... 
- python+opencv实现图像自适应阈值的均衡化
			内容涉及:列表遍历,图像均衡化,图像通道分离与合并 import cv2 import numpy as np import os for path in open("org_junheng ... 
