python_单例模式实现、部分魔术方法介绍(callable、__init__、__new__、__str__、__add__、__enter__、__exit__)、鸭子类型简介

python_单例模式实现、部分魔术方法介绍(callable、__init__、__new__、__str__、__add__、__enter__、__exit__)、鸭子类型简介,第1张

概述一。单例模式1)单例模式概念:只有一个实例2)实现方法:(1)import(2)单例模式(3)装饰器3)单例模式的原理:通过__new__(这个内置方法很懵逼吧,因为我们一般写代码用不到确实是存在并自己运行的,不要急下面介绍)实现单例模式:__new__的关系:__new__会先创

一。单例模式

1)单例模式概念:只有一个实例

2)实现方法:

    (1)import

    (2)单例模式

    (3)装饰器

3)单例模式的原理:通过__new__(这个内置方法很懵逼吧,因为我们一般写代码用不到确实是存在并自己运行的,不要急下面介绍)实现单例模式:

  __new__ 的关系:
  __new__ 会先创建对象并分配内存

4)单例模式的实现过程:

class Person(object):
obj = 2
def __init__(self):
pass

def __new__(cls, *args, **kwargs):
"""如果对象已经创建,就直接把创建好的对象返回
如果对象没有创建,就创建对象,并返回"""
if not cls.obj:
cls.obj = super().__new__(cls) #分配内存
return cls.obj
if __name__ == '__main__':
name_1 = Person()
name_2 = Person()
print(name_1 is name_2)
print(ID(name_1), ID(name_2))

运行结果(可以看出,name_1 与 name_2 虽然他们两个都赋值了 类Person 但是他们是一样的,也就是只有一个实例;当然这里我们就疑问类,是不是单例对我有什么影响那。设想下如果我们

调用的实例 他们都是可以变化的在你频繁调用该实例的时候对你有什么影响那?):

 

 

 

二。魔术方法:

1)callable:内置函数,判断对象能不能加括号运行

类方法加__call__使其可以加括号运行,具体作用请参考上一篇文章“python_...装饰器”

举栗:

  

def add(x, y):
return x + y


class MyClass(object):
pass

class MyClass2(object):
def __call__(self, *args, **kwargs):
pass
if __name__ == '__main__':
print(callable(add)) # 函数方法是可以加括号运行的,返回结果为:ture
print(callable(MyClass())) #类是不可以加括号运行的,返回结果为:fals

print(callable(MyClass2())) #想要使类加括号运行需要添加__call__内置方法:ture

 

2)__init__ 与 __new__

两者之间的关系:

__new__ 会先创建对象并分配内存,然后创建之后会返回一个对象(也就是self),然后会传给__init__,
然后,__init__参数会绑定到new创建的对象上(也就是self);如果new有值会重写init内容
#方式一:
class Person(object):
def __init__(self, name):
self.name = name
print('这里是__init__,会初始化对象的值')

def __new__(cls, *args, **kwargs):
print('这里是__new__会先创建对象并分配内存')
self = super().__new__(cls)
# 如果不写return返回的是none
return self
if __name__ == '__main__':
mingzi = Person('名字')

运行结果(运行结果可以看出来,__new__先创建对象并分配内存后返回self,然后__init__初始化对象的值):

 

 

 

#方式二,这里的__add__不明白没关系,在本章魔术方法:4)有专门解释:
class Myclass(object):
def __init__(self, value):
self.value = value

def __add__(self, other):
# self:第一个对象
# other:第二个对象
return self.value + other.value


if __name__ == '__main__':
# 巩固类与对象调用过程,前两行等价与 obj1 = Myclass(1)
obj3 = object.__new__(Myclass) # 创建对象,object是超级类
obj3.__init__(3) # 初始化对象
print(obj3.value) # 获取对象的属性value

运行结果:

 

 

 

3)__str__:自定义对象输出的样式,输出的需要是字符串

#查看List中是否有__str__内置方法
print(hasattr(List, "__str__")) # True
print([1, 2, 3])


class MyList(List):
def __str__(self): #__str__ 就是print对象时,对象输出的样子;自定义对象输出的样子,输出时需要是字符串
result = ''
for value in self:
result += str(value)
return f"{result}"


if __name__ == '__main__':
print(MyList([1, 2, 3, 4]))

运行结果:

 

 

 

4)__add__:对两个同类型的对象进行 + *** 作,会执行对象的 __add__ 方法。(若对象中没有__add__内置方法的定义在执行相加时会报错,这里不展示报错结果)

  

class Myclass(object):
def __init__(self,value):
self.value = value

def __add__(self, other):
#self:第一个对象
#other:第二个对象
return self.value + other.value


if __name__ == '__main__':
obj1 = Myclass(1)
obj2 = Myclass(2)
print(obj1 + obj2) # ==> print(obj1.__add__(obj2))
print(obj1.__add__(obj2))

运行结果:

 

 

 

5)__enter__ 与 __exit__:输入和退出内置方法,会先执行__enter__方法然后执行__exit__方法。这两个方法通常会用作 上下文管理器使用,比较常见的有 with 、open方法,

被with包裹的代码在执行前先执行__enter__方法,代码结束后会执行__exit__方法

 

  

#1.自定义__enter__ 与 __exit__方法,并使用with
class Myclass(object):

def __enter__(self):
print("enter...")

def __exit__(self, exc_type, exc_val, exc_tb):
print("exit...")

  

if __name__ == '__main__':
# 1.自定义__enter__、__exit__方法
obj = Myclass()
with obj as o:
print("~~~~~~~")

运行结果:

 

 

 

# 2.open
# # 典型的支持上下文管理器的方法:open 方法返回一个文件对象,文件对象支持上下文管理协议
f = open("temp.txt", 'w')
print(hasattr(f, '__enter__')) #返回:True
print(hasattr(f, '__exit__')) #返回:True
f.close()

 

三。鸭子类型:是动态中的风格,只在意你在方法不在意你的对象。使用场景(之一):发送消息

#实现1,不在意对象是否是Cat 或者是 Dog,只要方法相同即可,在方法f中调用此方法
class Cat(object):
def say(self):
print("maio~~~~")

class Dog(object):
def say(self):
print("wang~~~")


def f(obj):
"""obj 只要是用say方法的对象就行"""
obj.say()

#实现2
class Cat1(object):
def Listing(self):
print("maio~~~~1")

class Dog1(object):
def Listing(self):
print("wang~~~1")


def f1(obj):
"""obj 只要是用Listing方法的对象就行"""
obj.Listing()

if __name__ == '__main__':
#实现1
f(Cat())
f(Dog())

#实现2
f1(Cat1())
f1(Dog1())

运行结果:

 

总结

以上是内存溢出为你收集整理的python_单例模式实现、部分魔术方法介绍(callable、__init__、__new__、__str__、__add__、__enter__、__exit__)、鸭子类型简介全部内容,希望文章能够帮你解决python_单例模式实现、部分魔术方法介绍(callable、__init__、__new__、__str__、__add__、__enter__、__exit__)、鸭子类型简介所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1187985.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存