1,类的特殊方法  

新建一个类,本章内容中的特殊方法如果不创建类或新增方法,默认使用的就是下面的类:

  1. class Foo:
  2. """this is Foo"""
  3. typecode = 'd'
  4.  
  5. def __init__(self, x):
  6. self.x = x
  7.  
  8. def run(self):
  9. return self.x
  10.  
  11. f = Foo(1)

  

__doc__:类的描述信息

  1. print(f.__doc__) # this is Foo

  

__module_:对象所属modul,如果是当前执行文件的即__main__,如果是import的,可以查看所属的module

  1. print(f.__module__) # __main__
  1. import pandas as pd
  2. df = pd.DataFrame()
  3. print(df.__module__) # pandas.core.frame

  

__class__:对象所属类,等效于type

  1. print(f.__class__) # <class '__main__.Foo'>
  2. print(type(f)) # <class '__main__.Foo'>

  

__dir__:

函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;

  1. for i in dir():
  2. print(i)
  3.  
  4. 输出为:
  5. Foo
  6. __annotations__
  7. __builtins__
  8. __cached__
  9. __doc__
  10. __file__
  11. __loader__
  12. __name__
  13. __package__
  14. __spec__
  15. f

带参数时,返回参数的属性、方法列表。

  1. for i in dir(Foo):
  2. print(i)
  3.  
  4. 输出为:
  5. __class__
  6. __delattr__
  7. __dict__
  8. __dir__
  9. __doc__
  10. __eq__
  11. __format__
  12. __ge__
  13. __getattribute__
  14. __gt__
  15. __hash__
  16. __init__
  17. __init_subclass__
  18. __le__
  19. __lt__
  20. __module__
  21. __ne__
  22. __new__
  23. __reduce__
  24. __reduce_ex__
  25. __repr__
  26. __setattr__
  27. __sizeof__
  28. __str__
  29. __subclasshook__
  30. __weakref__
  31. run
  32. typecode

类的实例比类多了实例属性:

  1. print(set(dir(f)) - set(dir(Foo))) # {'x'}
  2. print(set(dir(Foo)) - set(dir(f))) # set()

__mro__:打印类的层次结构

  1. >>> FileNotFoundError.__mro__
  2. (<class 'FileNotFoundError'>, <class 'OSError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>)

__dict__:打印类/实例的属性

dict只能使用obj.__dict__,不能使用dict(obj),因为后者会被视为字典的初始化

打印所有实例的属性(不包括类属性):

  1. f = Foo(1)
  2. print(f.__dict__) # {'x': 1}

打印所有类属性(不包括实例的属性):

  1. for k, v in Foo.__dict__.items():
  2. print(k, v)
  3.  
  4. 输出为:
  5. __module__ : __main__
  6. __doc__ : this is Foo
  7. typecode : d
  8. __init__ : <function Foo.__init__ at 0x000001AC45314620>
  9. __dict__ : <attribute '__dict__' of 'Foo' objects>
  10. __weakref__ : <attribute '__weakref__' of 'Foo' objects> 

注意__dir__和__dict__的区别:前者显示类/实例所有的属性/方法(如果是实例显示的是类+实例的属性/方法),后者显示类/实例属性键值对(类和属性只会分别显示自己特有的)

__call__:让类的实例变为可调用

  1. class Foo:
  2.  
  3. def __call__(self, *args, **kwargs):
  4. return 1
  5.  
  6. print(Foo()()) # 1,第一次()是实例化,第二次()是调用

  

__get__、__set__、__delete__:描述符协议,属性的设置/取值/删除

__getattr__、__setattr__、__delattr__:动态属性的设值/取值/删除,详见类的属性

__getattribute__:获取已经存在的属性值,__getattr__是获取不存在的属性值的方法

__getitem__、__setitem__、__delitem__:[]运算符,分量的获取/设置/删除

  1. class Foo:
  2.  
  3. def __init__(self, components):
  4. self._components = sorted(components)
  5.  
  6. def __setitem__(self, key, value):
  7. self._components[key] = value
  8.  
  9. def __getitem__(self, item):
  10. return self._components[item]
  11.  
  12. def __repr__(self):
  13. return '<Foo: {}>'.format(self._components)

访问与设置分量:

  1. f = Foo([3, 5, 1, 9]) # <Foo: [1, 3, 5, 9]>
  2. print(f)
  3. print(f[1]) # 3
  4. f[0] = 10
  5. print(f) # <Foo: [10, 3, 5, 9]>

  

__enter__,__exit__:上下文管理器,先触发__enter__,再触发with代码块,最后触发__exit__

  1. class Foo:
  2.  
  3. def __enter__(self):
  4. return 'enter获取的内容' # 可以没有返回内容
  5.  
  6. def __exit__(self, exc_type, exc_val, exc_tb):
  7. print('exit时只需的内容')
  8.  
  9. with Foo() as f:
  10. print(f) # f获取的是__enter__返回的结果
  11.  
  12. 输出为:
  13. enter获取的内容
  14. exit时只需的内容

  

__slot__:存储实例属性方式改为元组方式

缺省存储实例属性是字典方式,在__dict__中,改为元组方式可以节省空间,但是属性范围受到slot元组限制

  1. class Foo:
  2. __slots__ = ('x', 'y')

  

__reversed__:反向迭代协议,让序列类型对象支持反向迭代,如果没有该协议,可以先把对象变成列表再用列表的反向迭代协议

  1. class Foo:
  2. def __init__(self, components):
  3. self.components = [x*x for x in components]
  4.  
  5. def __reversed__(self):
  6. return reversed(self.components) # 委托给self.components背后的生成器
  7.  
  8. f = Foo([1, 3, 5, 7, 9])
  9. for i in reversed(f):
  10. print(i)

__format__:

  1. _formats = {'ymd': '{d.year}-{d.month}-{d.day}',
  2. 'mdy': '{d.month}/{d.day}/{d.year}'}
  3.  
  4. class Foo:
  5.  
  6. def __init__(self, year, month, day):
  7. self.year = year
  8. self.month = month
  9. self.day = day
  10.  
  11. def __format__(self, code):
  12. if code == '':
  13. code = 'ymd'
  14. fmt = _formats[code]
  15. return fmt.format(d=self)
  16.  
  17. f = Foo(2019, 1, 25)
  18. print(format(f)) # 2019-1-25
  19. print(format(f, 'mdy')) # 1/25/2019

__new__:可以实例化时跳过构造函数

  1. class Date:
  2.  
  3. def __init__(self, year, month, day):
  4. self.year = year
  5. self.month = month
  6. self.day = day
  7.  
  8. >>>d = Date.__new__(Date)
  9. >>>d
  10. <__main__.Date object at 0x10b353400>
  11. >>>d.year
  12. AttributeError: 'Date' object has no attribute 'year'

__metaclass__:待补充

__init__:略

__del__:略

__str__:略

__repr__:返回的内容最好符合obj = eval(repr(obj)),即返回内容可以直接用来实例化

没有定义__repr__或者__str__时,返回的是对象的内存地址:

  1. class User:
  2. def __init__(self, user_id):
  3. self.user_id = user_id
  4. u = User(3)
  5. print(u) # <__main__.User object at 0x000002E85D7383C8>

使用猴子补丁定义__repr__,再打印u:

  1. def repr(instance):
  2. return 'User({})'.format(instance.user_id)
  3. User.__repr__ = repr
  4. u = User(3)
  5. print(u) # User(3)

u的repr返回内容可以直接拿来实例化:

  1. u1 = eval(repr(u))
  2. print(u1) # User(3)
  3. print(u is u1) # False,u和u1不是同一个实例

__contain__:in测试首先调用的特殊方法,下面自建了一个类似字典的Dict类,但是in测试测的是key,而不是values:

  1. class Dict:
  2.  
  3. def __init__(self, **kwargs):
  4. self.map = kwargs
  5.  
  6. def __contains__(self, item):
  7. if item in self.map.values():
  8. return True
  9.  
  10. d = Dict(a=1, b=2)
  11. print('a' in d) # False
  12. print(1 in d) # True

2,操作需要支持的特殊方法

序列:__len__,__getitem__

切片:__getitem__

迭代/元组拆包:1)__iter__;2)__getitem__(index从0开始)

可散列:__hash__,__eq__

in测试:1)__contains__;2)__iter__;3)__getitem__

描述符:__set__,__get__,__delete__ (可部分实现)

动态属性存取:__getattr__、__setattr__、__delattr__

[]分量存取:__getitem__、__setitem__、__delitem__

运算符+= :1)__iadd__,2)__add__

上下文管理器:__enter__,__exit__

反向迭代:__reversed__

guxh的python笔记八:特殊方法的更多相关文章

  1. guxh的python笔记一:数据类型

    1,基本概念 1.1,数据类型 基本数据类型:字符串,数字,布尔等 引用数据类型:相对不可变(元组),可变(列表,字典,集合等) 基本数据类型存放实际值,引用数据类型存放对象的地址(即引用) ==:判 ...

  2. guxh的python笔记七:抽象基类

    1,鸭子类型和白鹅类型 1.1,白鹅类型 白鹅类型对接口有明确定义,比如不可变序列(Sequence),需要实现__contains__,__iter__,__len__,__getitem__,__ ...

  3. guxh的python笔记五:面向对象

    1,面向对象编程思想 类:一类具有相同属性的抽象 属性(静态属性):实例变量.类变量.私有属性 方法(动态属性):构造函数.析构函数(默认就有).函数.私有函数 对象/实例:类经过实例化后,就是对象/ ...

  4. guxh的python笔记二:函数基础

    1,函数的参数 1.1,查看函数的参数类型 def run(a, *args, b, **kwargs): return a + b 可以通过如下方式查看参数类型: import inspect k ...

  5. guxh的python笔记三:装饰器

    1,函数作用域 这种情况可以顺利执行: total = 0 def run(): print(total) 这种情况会报错: total = 0 def run(): print(total) tot ...

  6. guxh的python笔记十:包和模块

    1,包和模块 包package:本质就是一个文件夹/目录,必须带一个__init.__.py的文件 模块module:.py结尾的python文件 2,导入方法 import pandas, coll ...

  7. guxh的python笔记十一:异常处理

    1,抓错方法 name = [0, 1, 2] try: name[3] except IndexError as exc: # 抓单个错误,打印错误信息e print(exc) except (In ...

  8. guxh的python笔记六:类的属性

    1,私有属性 class Foo: def __init__(self, x): self.x = x 类的属性在实例化之后是可以更改的: f = Foo(1) print(f.x) # 1 f.x ...

  9. guxh的python笔记四:迭代

    1,可迭代对象iterable,迭代器iterator,生成器generator 可迭代对象iterable: 实现__iter__方法的类.__iter__方法返回iterator或者generat ...

随机推荐

  1. iOS学习之Object-C语言属性和点语法(转载收集)

    一.属性      1.属性的声明:在.h文件中使用@property声明属性.           @property NSString *name;       2.属性的作用是生成setter以 ...

  2. MVC中code first方式开发,数据库的生成与更新

    在使用EF的实际编程中我们经常遇到这样的问题:发现实体结构需要新增加一个字段,或者减少一个字段,急需把实体结构修改,并让数据库更新这种修改.在用Model First或者Database First的 ...

  3. Axure RP 8过期,用户名和序列号(注册码)

    用户名:axureuser 序列号:8wFfIX7a8hHq6yAy6T8zCz5R0NBKeVxo9IKu+kgKh79FL6IyPD6lK7G6+tqEV4LG 用户名:aaa注册码:2GQrt5 ...

  4. 56.关于vue项目的seo问题

    不可否定的是,vue现在火.但是在实际项目中,特别是像一下交互网站,我们不可避免会考虑到的是seo问题,这直接关系到我们网站的排名,很多人说用vue搭建的网站不能做优化,那我们真的要放弃vue,放弃前 ...

  5. js跨域交互之jsonp - 看完就能让你了解jsonp原理 (原)

    跨域? 跨域的安全限制都是对浏览器端来说的,服务器端是不存在跨域安全限制的. 同源策略? 一般来说 a.com 的网页无法直接与 b.com的服务器沟通, 浏览器的同源策略限制从一个源加载的文档或脚本 ...

  6. spring 获取对象的注解

    BeanDefinition definition = registry.getBeanDefinition(name); if (definition instanceof AnnotatedBea ...

  7. matlab将rgb图转为灰度图的原理代码

    MyYuanLaiPic = imread('e:/image/matlab/Cluo.jpg');%读取RGB格式的图像 MyFirstGrayPic = rgb2gray(MyYuanLaiPic ...

  8. (Review cs231n) Optimized Methods

    Mini-batch SGD的步骤: 1.Sample a batch of data 2.Forward prop it through the graph,get loss 3.backprop ...

  9. git忽略某些文件的几种方法

    不知道为什么我记得我写过这个内容但是又找不到了,只好照着大致记忆写一下以备留存. 1.首先肯定是.gitignore文件 .gitignore文件适合在文件尚未被追踪时加入,将其忽略便可以不上传到远程 ...

  10. 一文理解 Java NIO 核心组件

    同步.异步.阻塞.非阻塞 首先,这几个概念非常容易搞混淆,但NIO中又有涉及,所以总结一下[1]. 同步:API调用返回时调用者就知道操作的结果如何了(实际读取/写入了多少字节). 异步:相对于同步, ...