面向对象的进阶(item系列,__new__,__hash__,__eq__)

一、item系列

getitem、setitem、delitem(操作过程达到的结果其实就是增删改查)
class Foo:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex def __getitem__(self, item): # 与f['xx']形式对应
if hasattr(self, item):
return self.__dict__[item] def __setitem__(self, key, value): # 与f['xx']='ss'形式对应
self.__dict__[key] = value def __delitem__(self, key): # 与del f['xx']形式对应
del self.__dict__[key] f = Foo('egon',30,'男')
print(f['name'])
# f['name']---对象['xx']这种形式就会触发前面的__getitem__方法,将name就传给了item
# 支持以这样的方式取得了对象的属性name,正常的是f.name取到属性 f['hobby'] = '男'
# 新增加的key和value,触发__setitem__方法,将对应的属性和值放入原本的字典中
print(f['hobby'], f.hobby)
# 以f['hobby']这样的方式取到新增的属性,原本正常取值f.hobby # del f.hobby # 正常的删除方式
# print(f.hobby) # 此时会报错,显示:AttributeError: 'Foo' object has no attribute 'hobby' del f['hobby']
# 如果执行到这步,就会显示:AttributeError: __delitem__,显示没有这个方法
# 这个删除方式就触发__delitem__方法,前面类里面就必须得有定义该方法
print(f.__dict__) # 字典里面就没有hobby的属性了

运行结果:

C:\Users\3-2\PycharmProjects\untitled\venv\Scripts\python.exe C:/Users/3-2/PycharmProjects/untitled/面向对象进阶.py
egon
男 男
{'sex': '男', 'age': 30, 'name': 'egon'} Process finished with exit code 0
这种用中括号就可以直接调的方式,比如用字典,列表的实现过程,就是内部存在了item系列这个机制的原因
这种用中括号就可以直接调的方式,比如用字典,列表的实现过程,就是内部存在了item系列这个机制的原因
object原生支持__delattr__所以才可以直接del f.hobby而不报错,但是del f['hobby']得通过自己实现,
所以当类方法里面没有__delitem__的时候就会报错
二、__new__
__init__:初始化方法
__new__:构造方法,创建一个对象。self就是__new__构造出来的,即__new__方法是self产生的机制
平时是不需要用到执行__new__方法的,以下例子只是简单说明它是怎么用的:
class A:
def __init__(self):
self.x = 1
print('in init function')
def __new__(cls, *args, **kwargs):
# 传入一个默认参数cls,执行__new__方法前还没有self,所以只能传一个类进来
print('in new function')
return object.__new__(A,*args,**kwargs)
# object.__new__创造了一个新的对象,然后将这个对象传给self的位置,所以当执行self的时候就可以使用对象了 a = A() # 实例化,会先执行__new__方法,再执行 __init__方法

运行结果:

in new function
in init function Process finished with exit code 0
一个典型的设计模式(23种):单例模式
单例模式:一个类始终只有一个实例;当第一次实例化这个类的时候就创建一个实例化的对象;当之后再来实例化的时候,
就会用之前创建的对象
# 实现单例模式的例子:

class A:
__instance = False # 私有的静态变量 不希望别人可以使用,必须得经过自己的设置
def __init__(self,name,age):
self.name = name
self.age = age def __new__(cls, *args, **kwargs):
if cls.__instance: # 如果为真就执行下面代码,否则执行后面的代码
# 第二次进来的时候就符合这个了
return cls.__instance # 第二次进来就直接将之前创建的对象返回给self了
cls.__instance = object.__new__(A)
# 因为第一次进来的时候就是__instance = False,所以执行这行代码代码
# 用object.__new__创建一个类A的新的对象,并且赋值给 cls.__instance
return cls.__instance # 这里就是将新建的对象return回去 egon = A('egg',38)
# 真正能实例化对象并且占用内存的是object里面的self,但是这里使用的对象始终是object.__new__创建的,
# 因为自己就有对象了,就不会去使用object里面的了
# 反正能够实现单例化的原因是__new__方法的使用
egon.cloth = '小花袄'
nezha = A('nazha',25)
nezha.shoes = '小白鞋'
print(nezha)
print(egon)
# 执行到这里根据运行结果显示内存地址是同一个,也就是说第二次实例化的时候是在对第一个实例化后的
# 对象进行操作的,而并没有再次创建另一个占内存的对象,如果第二次实例化传的参数和原对象一致,
# 参数值就会进行覆盖,如果第二次实例化传的参数只是原属性的一部分,则相同的覆盖,原来的继续会
# 在表现在现有对象中
print(nezha.name)
print(egon.name)
# 执行到这里原来egon的名字已经被nezha覆盖了
print(nezha.cloth)
# 执行到这里原来egon的cloth会继续穿在nezha上

运行结果:

<__main__.A object at 0x0000025C0C2293C8>
<__main__.A object at 0x0000025C0C2293C8>
nazha
nazha
小花袄

三、__hash__

# 在没有定义__hash__方法的时候,hash都是针对内存地址的,而不是针对对象属性,内存地址不一样,hash的结果也不一样 

class A: 
  def __init__(self,name,sex):
    self.name = name
a = A('egn','男')
b = A('egon','nv')
print(hash(a))
print(hash(b))

运行结果:

154259419512
154259419617
# 定义了—__hash__方法后,属性不同hash值也会不同,属性相同hash值也会相同:
class A:
def __init__(self,name,sex):
self.name = name
self.sex = sex
def __hash__(self):
return hash(self.name+self.sex) a = A('egon','男')
b = A('egon','男')
c = A('egon','nv')
print(hash(a))
print(hash(b))
print(hash(c))

运行结果:

8385798543724353936
8385798543724353936
-7270162062837990016

四、__eq__

没有__eq__方法的时候,两者比较是比较内存地址:
class A:
def __init__(self,name):
self.name = name obj1 = A('egg')
obj2 = A('egg')
print(obj1 == obj2)
# 没有定义__eq__方法的时候,比较时候默认比较内存地址,上面两个内存地址是不一样的

运行结果:

False
# 定义__eq__方法时可以自己设定执行内容,‘==’触发的_eq_方法
class A:
def __init__(self,name):
self.name = name def __eq__(self, other):
if self.name == other.name:
return True
else:
return False obj1 = A('egg')
obj2 = A('egg')
obj3 = A('EGG')
print(obj1 == obj2) # 等号触发的__eq__
print(obj2 == obj3) # 等号触发的__eq__

运行结果:

True
False Process finished with exit code 0

面向对象的进阶(item系列,__new__,__hash__,__eq__)的更多相关文章

  1. 面向对象进阶-item系列、__new__、__hash__、__eq__ (四)

    item系列 dic = {'k':'v'}# 对象 : 存储属性 和调用方法dic['k'] = 'v'# class Foo:#     def __init__(self,name,age,se ...

  2. __del__,item系列 ,hash方法,__eq__,

    # 构造方法 申请一个空间# 析构方法 释放一个空间 # 某个对象借用了操作系统的资源,还要通过析构方法归还回去:文件资源 网络资源 # 垃圾回收机制 class A: def __del__(sel ...

  3. 面向对象 反射 和item系列和内置函数和__getattr__和__setattr__

    反射 反射主要用在网络编程中, python面向对象的反射:通过字符串的形式操作对象相关的属性.python的一切事物都是对象. 反射就是通过字符串的形式,导入模块:通过字符串的形式,去模块寻找指定函 ...

  4. python 全栈开发,Day24(复习,__str__和__repr__,__format__,__call__,__eq__,__del__,__new__,item系列)

    反射: 使用字符串数据类型的变量名来使用变量 wwwh即what,where,why,how  这4点是一种学习方法 反射 :使用字符串数据类型的变量名来使用变量 1.文件中存储的都是字符串 2.网络 ...

  5. 1、__del__ 2、item系列 3、__hash__ 4、__eq__

    1.__del__   析构方法       释放一个空间之前之前 垃圾回收机制   2.item系列   和对象使用[ ]访问值有联系 __getitem__ __setitem__ __delit ...

  6. day7--面向对象进阶(内含反射和item系列)

    一面向对象的结构和成员 1.1面向对象的结构 class A: company_name = '老男孩教育' # 静态变量(静态字段) __iphone = '1353333xxxx' # 私有静态变 ...

  7. python面向对象( item系列,__enter__ 和__exit__,__call__方法,元类)

    python面向对象进阶(下)   item系列 __slots__方法 __next__ 和 __iter__实现迭代器  析构函数 上下文管理协议 元类一.item系列 把对象操作属性模拟成字典的 ...

  8. Day 28面向对象的进阶-内置函数(__new__,__del__)

     元类 创造 类  所有类的type 都是他的元类 类创造 对象   具体创造对象的方法 __new__方法 class 类名(classmata = type)#默认是 class 类名(class ...

  9. what' the python之面向对象(进阶)

    面向对象的知识点补充(进阶版) classmethod和staticmethod:这两个函数的用途就是可以不用实例化对象就可以调用方法 class Classmethod_Demo(): role = ...

随机推荐

  1. Learning Markov Clustering Networks for Scene Text Detection

    Learning Markov Clustering Networks for Scene Text Detection 论文下载:https://arxiv.org/pdf/1805.08365v1 ...

  2. Vue——watch监听对象,监听嵌套多次的对象属性

    首先是watch 然后是methods

  3. JavaScript笔记十一

    1.DOM查询 - 通过具体的元素节点来查询 - 元素.getElementsByTagName() - 通过标签名查询当前元素的指定后代元素 - 元素.childNodes - 获取当前元素的所有子 ...

  4. pynlp报错:pynlpir.LicenseError: Your license appears to have expired. Try running "pynlpir update"解决办法。

    使用pyltp做文本挖掘时报错: pynlpir.LicenseError: Your license appears to have expired. Try running "pynlp ...

  5. JSONPath入门之Snack3篇

    Snack3 for java 一个微型JSON框架 基于jdk8,60kb.有序列化反序列化.解析和转换.支持 Json path 查询. <dependency> <groupI ...

  6. Sql 修改表结构

    添加字段 alter table 表名 add 字段名 nvarchar(100) not null 修改字段 alter table 表名 alter column 字段名 int not null ...

  7. 记一次 Java 项目 CPU 占用久高不下故障处理

    事件背景 公司对接了新系统,代码变动很大,项目也很急,于是在上线之后 Zabbix 不时就告警,提示 CPU 使用过载,告警消息类似如下: 一开始以为是系统停机升级,所有人都等着使用系统,导致系统处理 ...

  8. master节点的部署介绍和前置工作

    目录 组件介绍 组件介绍 kubernetes master节点运行组件如下: kube-apiserver.kube-scheduler.kube-controller-manager.kube-n ...

  9. kubectl: Error from server: error dialing backend: remote error: tls: internal error

    使用kubectl logs,发现报了tls的错误,然后查看kubelet的日志,发现报了上面的错误,然后通过命令kubectl get csr查看发现有很多处于pending状态 最后通过命令 ku ...

  10. MySQL详解

    MySQL详解 什么是数据库 # 用来存储数据的仓库 # 数据库可以在硬盘及内存中存储数据 # 数据库与文件存储数据区别 # 数据库本质也是通过文件来存储数据, 数据库的概念就是系统的管理存储数据的文 ...