面向对象的进阶(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. (四十四)golang--协程(goroutine)和管道(channel)相结合实例

    统计1-8000之间的素数. 整体框架: 说明:有五个协程,三个管道.其中一个协程用于写入数字到intChan管道中,另外四个用于取出intChan管道中的数字并判断是否是素数,然后将素数写入到pri ...

  2. Lab4\5:进程和线程

    进程的定义 进程是指一个具有一定独立功能的程序在一个数据集合上的一次动态执行过程 源代码在经过编译链接之后生成了可执行文件,再由操作系统进行加载并且进行一些堆栈的分配才是进程 进程控制块 操作系统管理 ...

  3. Sublime Text最好的中文教程

    原文链接:http://lucida.me/blog/sublime-text-complete-guide/ 摘要(Abstract) 本文系统全面的介绍了Sublime Text,旨在成为最优秀的 ...

  4. opencv简介以及环境搭建

    1.opencv简介 opencv:全称:Open Source Computer Vision Library 是一个跨平台的计算机视觉库 可用于开发实时的图像处理.计算机视觉以及模式识别程序 应用 ...

  5. telnet指令研究—以网络聊天程序为例

    一.telnet指令 Telnet取名自Telecommunications和Networks的联合缩写,是早期个人计算机上连接到服务器主机的一个网络指令,由于存在安全问题,现在已经很少被使用.在wi ...

  6. Django中间件部分源码分析

    中间件源码分析 中间件简介 中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量.低级别的插件系统,用于在全局范围内改变Django的输入和输出.每个中间件组件都负责做一些特定的 ...

  7. Spring 框架基础(06):Mvc架构模式简介,执行流程详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.SpringMvc框架简介 1.Mvc设计理念 MVC是一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集 ...

  8. mac安装pip

    1.下载get-pip.py curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py SaintKings-Mac-mini ...

  9. Tensorflow Serving Docker compose 部署服务细节(Ubuntu)

    [摘要] Tensorflow Serving 是tf模型持久化的重要工具,本篇介绍如何通过Docker compose搭建并调试TensorFlow Serving TensorFlow Servi ...

  10. Vue全家桶高仿小米商城

    大家好,我是河畔一角,时隔半年再次给大家带来一门重量级的实战课程:<Vue全家桶高仿小米商城>,现在很多公司都在参与到商城的构建体系当中,因此掌握一套商城的标准开发体系非常重要:商城的开始 ...