Python 入门 之 双下方法

1、双下方法

​ 定义:双下方法是特殊方法,它是解释器提供的 由双下划线加方法名加双下划线 方法名的具有特殊意义的方法,双下方法主要是python源码程序员使用的,我们在开发中尽量不要使用双下方法,但是深入研究双下方法,更有益于我们阅读源码。

(1)调用:不同的双下方法有不同的触发方式,

<1> __ len__ -- len() 触发

class A(object):

    def __init__(self,name):
self.name = name
print("触发了__init__") def __len__(self): # len() 触发
print("走这里")
return len(self.name) # return len("xqrqwr") str中__len__
# 必须有返回值,返回值的类型必须是整型 a = A("xqrqwr")
print(len(a)) # str
a = "12345" # str这个类的实例
lst = [1,2,3,4,4,5,5,5,5] # list这个类的实例
print(len(a))
print(len(lst))

<2> __ hash__ --hash() 触发

class A(object):

    def __init__(self,name,age):
self.name = name
self.age = age def __hash__(self): # hash()
hash({1,2,345}) # 可变数据类,不可数据类型
return 1
# 必须有返回值,返回值的类型必须是整型 a = A("meet",25)
print(hash(a))

<3> __ str__ --print 或者 str() 触发

class A:

    def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex def __str__(self): # print 触发 str()
print(111)
return f"姓名:{self.name} 年龄:{self.age} 性别:{self.sex}"
# 必须有返回值,返回值的类型必须是字符串 a = A("mee",20,"男")
a1 = A("mee1",200,"男1")
str(a)
print(a)
print(a1) # 以下对比:
a = A("mee",20,"男")
a1 = A("mee2",200,"女") print(f"姓名:{a.name} 年龄:{a.age} 性别:{a.sex}") # "姓名:meet 年龄:20 性别:男"
print(f"姓名:{a1.name} 年龄:{a1.age} 性别:{a1.sex}") # "姓名:meet2 年龄:200 性别:女"

<4> __ repr__ --print 或者 %r 触发

class A:

    def __init__(self):
pass def __repr__(self): # print触发 %r
print(1111)
return "天魔" def __str__(self): # str 优先级高于 repr 两个都存在就只执行str
return "小元" a = A()
print("%r"%(a))

<5> __ call__ --对象调用时触发,对象后加括号即:对象() 或者 类()()

class A:

    def __init__(self):
pass def __call__(self, *args, **kwargs): # 对象()时调用的__call__
print("走我")
print(*args, **kwargs) a = A()
a()

<6> __ eq__ 等于

class A(object):

    def __init__(self,name,age):
self.name = name
self.age = age def __eq__(self, other): # a == a1
if self.name == other.name:
return True
else:
return False a = A("mee",56)
a1 = A("mee",108) print(a == a1)

<7> __ del__ 构造方法,当对象在内存中被释放时,自动触发执行

​ 此方法一般情况下无需定义,因为python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为内存的分配和释放都是交给python解释器类执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

class A:
def __init__(self):
pass def __del__(self): del 触发
print("删除时执行我") a = A() import time
time.sleep(5)
del a a = 1
b = a
a = b
垃圾回收机制:
# 80 5/s
# 引用计数
# 标记清除
# 分袋回收 袋一:10 2/h 袋二: 5/3 4h 袋三: 3 20h

<8> __ item__ 系列 可以像操作字典一样操作实例方法

dic["键"] = 值
del dic["键"]
dic["键"]
class A:

    def __init__(self,name,age):
self.name = name
self.age = age def __getitem__(self, item):
print(self.__dict__)
print(self.__dict__[item]) # self.__dict__ 获取的就是字典 def __setitem__(self, key, value):
self.__dict__[key] = value def __delitem__(self, key):
del self.__dict__[key] a = A("meet",58)
a["sex"] = "男"
a["sex"]
del a["sex"]
print(a.__dict__)

<9> __ new__ 单例模式(工厂模式)

​ 单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

class A(object):

    def __init__(self,name):  # 初始化
self.name = name
print("我是__init__,先走我") def __new__(cls, *args, **kwargs):
print("我是__new__,先走我")
return "啦啦啦" a = A("meet")
print("我是谁:",a)
class A(object):

    def __init__(self,name):  # 初始化
self.name = name
print("我是__init__,先走我") def __new__(cls, *args, **kwargs):
obj = object.__new__(A)
print("我在哪:",obj)
return obj # obj == __init__() a = A("meet")
print("我是谁:",a)
class A(object):

    def __init__(self,name): # 初识化
self.name = name def __new__(cls, *args, **kwargs):
obj = object.__new__(A) # 调用的是object类中的__new__ ,只有object类中的__new__能够创建空间
return obj #本质: obj == __init__() return __init__() # 触发了__init__方法 a = A("mee") # a是对象的内存地址
a1 = A("天魔") # a是对象的内存地址
a2 = A("天阳") # a是对象的内存地址
print(a.name)
print(a1.name)
print(a2.name)
# 先执行__new__方法再执行__init__方法

class A:
__a = None #__a = 0x000001F346079FD0 def __init__(self,name,age):
self.name = name
self.age = age def __new__(cls, *args, **kwargs):
if cls.__a is None:
obj = object.__new__(cls)
cls.__a = obj
return cls.__a a = A("mee",123) # 地址0x000001F346079FD0
a1 = A("天魔",11)
print(a.name)
print(a1.name)
单例模式:不管创建多少次,使用的都是同一个内存空间
模块的导入,手写的单例模式
实例化对象时发生的事:
创建对象,并开辟对象空间 __ next__
自动执行 __ init方法,隐性的将对象地址传给self
将对象属性封装到对象空间

2、上下文

(1)__ enter__

(2)__ exit__

class my_open:

    def __init__(self,file,mode="r",encoding="utf-8"):
self.file = file
self.mode = mode
self.encoding = encoding def __enter__(self):
self.f = open(self.file,self.mode,encoding=self.encoding)
return self.f def __exit__(self, exc_type, exc_val, exc_tb):
print(exc_type,exc_val,exc_tb) # 没有错误时就是None
self.f.close() with my_open("a.txt") as ffff:
for i in ffff:
print(i)
print(ffff.read(1111))
print(ffff.read())

Python 入门 之 双下方法的更多相关文章

  1. python之路-双下方法

    双下方法 定义: 双下方法是特殊方法,他是解释器提供的,由双下线加方法名加双下划线 __方法名__具有特殊意义的方法 双下方法主要是Python源码程序员使用的,元编程 我们在开发中尽量不要使用双下方 ...

  2. 百万年薪python之路 -- 面向对象之 反射,双下方法

    面向对象之 反射,双下方法 1. 反射 计算机科学领域主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省) python面向对象中的反射:通过字符串的形式操作对象相关的属性.python ...

  3. Python面向对象 | 双下方法

    定义:双下方法是特殊方法,他是解释器提供的.由双下划线+方法名+双下划线 .它具有特殊意义的方法,双下方法主要是python源码程序员使用的,我们在开发中尽量不要使用双下方法,但是深入研究双下方法,更 ...

  4. Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究

    Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究 一丶反射 什么是反射: ​ 反射的概念是由Smith在1982年首次提出的 ...

  5. Python反射和内置方法(双下方法)

    Python反射和内置方法(双下方法) 一.反射 什么是反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发 ...

  6. Python面向对象之反射,双下方法

    一. 反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序 ...

  7. Python面向对象06 /元类type、反射、函数与类的区别、特殊的双下方法

    Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3 ...

  8. python 面向对象专题(六):元类type、反射、函数与类的区别、特殊的双下方法

    目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3. 函数与类的区别 4. 特殊的双下方法 1. 元类type type:获取对象 ...

  9. python之面向对象函数与方法,反射,双下方法

    一.函数和方法 1.函数和方法的区别 函数: 全都是显性传参,手动传参,与对象无关 方法: 存在隐性传参,与对象有关 1.1通过函数名可以判断 len()就是函数 str.count()就是方法 de ...

随机推荐

  1. CodeForces 754D Fedor and coupons ——(k段线段最大交集)

    还记得lyf说过k=2的方法,但是推广到k是其他的话有点麻烦.现在这里采取另外一种方法. 先将所有线段按照L进行排序,然后优先队列保存R的值,然后每次用最小的R值,和当前的L来维护答案即可.同时,如果 ...

  2. Vue2实践computed监听Vuex中state对象中的对象属性时发生的一些有趣经历

    今天想实现一个功能,在全局中随时改变用户的部分信息.这时候就想到了用Vuex状态控制器来存储用户信息,在页面中使用computed来监听用户这个对象.看似一个很简单的逻辑,就体现了我基本功的不扎实呀. ...

  3. 基于Redis的分布式锁安全性分析-转

    基于Redis的分布式锁到底安全吗(上)?  2017-02-11 网上有关Redis分布式锁的文章可谓多如牛毛了,不信的话你可以拿关键词“Redis 分布式锁”随便到哪个搜索引擎上去搜索一下就知道了 ...

  4. 访问H2数据库的SpringBoot工程

    JDK:1.8.0_212 IDE:STS4(Spring Tool Suit4 Version: 4.3.2.RELEASE) 工程下载:https://files.cnblogs.com/file ...

  5. DP&图论 DAY 5 上午

    DP&图论  DAY 5  上午 POJ 1125 Stockbroker Grapevine 有 N 个股票经济人可以互相传递消息,他们之间存在一些单向的通信路径.现在有一个消息要由某个人开 ...

  6. GitHub-Microsoft:DotNet4

    ylbtech-GitHub-Microsoft:DotNet4 1.返回顶部 · dotnet-template-samples Samples showing how to create temp ...

  7. 代码实现:定义一个文件输入流,调用read(byte[] b)方法,将a.txt文件中的内容打印出来(byte数组大小限制为5)

    package com.loaderman.test; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; im ...

  8. kvm网络虚拟化(vlan,bond,vlan+bond)(3)

    一.Linux Bridge网桥管理 网络虚拟化是虚拟化技术中最复杂的部分,也是非常重要的资源. VM2 的虚拟网卡 vnet1 也连接到了 br0 上. 现在 VM1 和 VM2 之间可以通信,同时 ...

  9. linux常用命令(11)less命令

    less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大.less 的用法比起 more 更加的有弹性.在 more 的时候,我们并没有办法向前面翻 ...

  10. PHP define defined const

    define 定义常量,常量一旦被定义,在脚本执行期间就不能再改变或者取消定义 常量默认大小写敏感.通常常量标识符总是大写的 与变量的区别: 1.常量前面没有美元符号($) 2.常量只能通过defin ...