__str__和__repr__,__format__

改变对象的字符串显示__str__,__repr__

自定制格式化字符串__format__

#_*_coding:utf-8_*_

format_dict={
'格式1':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
'格式2':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
'格式3':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
}
class School:
def __init__(self,name,addr,type):
self.name=name
self.addr=addr
self.type=type def __repr__(self):
return 'School(%s,%s)' %(self.name,self.addr)
def __str__(self):
return '(%s,%s)' %(self.name,self.addr) def __format__(self, format_spec):
# if format_spec
if not format_spec or format_spec not in format_dict:
format_spec='格式1'
fmt=format_dict[format_spec]
return fmt.format(obj=self) s1=School('清华','北京','公立')
print('from repr: ',repr(s1))
print('from str: ',str(s1))
print(s1) '''
str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
'''
'''
注意:这三个方法的返回值必须是字符串,否则抛出异常
'''
print(format(s1,'格式1'))
print(format(s1,'格式2'))
print(format(s1,'格式3'))
print(format(s1,'xxx'))

class B:

     def __str__(self):
return 'str : class B' def __repr__(self):
return 'repr : class B' b=B()
print('%s'%b)
print('%r'%b)

__del__

析构方:当对象在内存中被释放的同时自动触发执行该方法。

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

class Foo:

    def __del__(self):
print('执行我啦') f1=Foo()
del f1
# 执行我啦
print('------->')
f1
# NameError: name 'f1' is not defined

item系列

__getitem__\__setitem__\__delitem__

  ==》__dict__

在Python中,如果我们想实现创建类似于序列和映射的类,可以通过重写魔法方法__getitem__、__setitem__、__delitem__方法去模拟。

这些魔术方法的原理就是:当我们对类的属性item进行下标的操作时,首先会被__getitem__()、__setitem__()、__delitem__()拦截,从而进行我们在方法中设定的操作,如赋值,修改内容,删除内容等等。

对类的属性item进行下标的操作==>obj["属性"]

class A:
def __init__(self,name):
self.name=name def __getitem__(self, item):
print("呵呵你看不到") def __setitem__(self, key, value):
self.__dict__[key]=value
print('设置了 obj 属性 [%s] 为 %s'%(key,value)) def __delitem__(self, key):
print('del obj[%s]时,我执行'%key)
self.__dict__.pop(key) def __delattr__(self, item):
print('del obj.%s时,我执行'%item)
self.__dict__.pop(item) def __setattr__(self, item,value):
print("调用了__setattr__方法")
self.__dict__[item]=value def daren(self):
pass a=A('斌哥')
#这个过程也调用了__setattr__方法 print(a.__dict__)
# {'name': '斌哥'} a.name
#==>'斌哥' print(a['name'])
#调用了__getitem__方法
# 呵呵你看不到
# None a['age']=18
#=触发=__setitem__>设置了 obj 属性 [age] 为 18
a.age=19
#=触发=__setitem__>调用了__setattr__方法
a['appear']='很帅'
# #=触发=>设置了 obj 属性 [appear] 为 很帅 del a.appear
#触发__delattr__==>del obj.appear时,我执行
del a['age']
#触发__delitem__==>del obj[age]时,我执行
a.school='nc'
print(a.__dict__)
# {'school': 'nc', 'name': '斌哥'}
# 结论:感觉属性维护了一个doc字典 # 结论 : obj.属性 调用 使用的是xxattr()方法
#xxitem()方法提供了 访问属性一个【】接口

__dict__

发现dict是一个mappingproxy类型,为何不是一个简单的python dict呢?

>>> class A(object): pass
...
>>> A.__dict__
mappingproxy({'__module__': '__main__', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None})

不清楚,回头研究下。

Python的实例有自己的__dict__,它对应的类也有自己的__dict__   (但是有些特殊的对象是没有__dict__属性的)

class A:
def __init__(self,name):
self.name=name
def __len__(self):
return len(self)
a=A('斌哥')
print(A.__dict__)
# {'__doc__': None, '__module__': '__main__', '__len__': <function A.__len__ at 0x0000014FF1C71EA0>,
# '__init__': <function A.__init__ at 0x0000014FF1BE1730>, '__weakref__': <attribute '__weakref__' of 'A' objects>,
# '__dict__': <attribute '__dict__' of 'A' objects>} print(a.__dict__)
# {'name': '斌哥'} class B(A):
def __init__(self,age,name):
super().__init__(name)
self.age=age
def __len__(self):
return len(self)
b=B(18,"bb")
print(B.__dict__)
print(b.__dict__) # {'__doc__': None, '__module__': '__main__',
# '__init__': <function B.__init__ at 0x0000014FF1CB1A60>,
# '__len__': <function B.__len__ at 0x0000014FF1CB1730>}
#
# {'name': 'bb', 'age': 18}
class A:
a = 0
b = 1 def __init__(self):
self.a = 2
self.b = 3 def test(self):
print('a normal func.') @staticmethod
def static_test(a):
print('a static func.'+a) @classmethod
def class_test(cls):
print('a calss func.') obj = A()
print(A.__dict__)
print(obj.__dict__)
A.static_test("")
A.class_test()

1.类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类__dict__里的

2.对象的属性(不含类的)保存在实例__dict___

3.子类有自己的__dict__, 父类也有自己的__dict__,子类的全局变量和函数放在子类的dict中,父类的放在父类dict中。对象也这样。

4.内置的数据类型没有__dict__属性

__dir__

dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。

dir([object])

参数说明:

  • object -- 对象、变量、类型。
class A(object): pass
a=A()
a.name="wqbin" print(A.__dict__)
print(a.__dict__)
print(a.__dir__())

Note:dir是最大范围的收集一个类或者一个对象的属性,所以是包含__dict__.keys

__call__

对象后面加括号,触发执行。

对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

class C:

    def __init__(self):
print("__init__") def __call__(self, *args, **kwargs): print('__call__') obj = C() # 执行 __init__
obj() # 执行 __call__

为什么函数对象可以触发?

f = abs

print(dir(f))

__len__

果一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。

要让 len() 函数工作正常,类必须提供一个特殊方法__len__(),它返回元素的个数。

class A:
def __init__(self):
self.a = 1
self.b = 2 def __len__(self):
return len(self.__dict__)
a = A()
print(len(a))
#2

__hash__

class A:
def __init__(self):
self.a = 1
self.b = 2 def __hash__(self):
return hash(str(self.a)+str(self.b))
a = A()
print(hash(a))
class A:
def __init__(self):
self.a = 1
self.b = 2 def __hash__(self):
# return str(self.a)+'哈哈'+str(self.b) return int(str(1024)+str(self.a)+str(self.b))
a = A()
print(hash(a))
# TypeError: __hash__ method should return an integer

__eq__

__eq__ 当判断两个对象的是否相等时,==触发此方法

class A:
def __init__(self):
self.a = 1
self.b = 2 def __eq__(self,obj):
if self.a == obj.a and self.b == obj.b:
return True
a = A()
b = A()
print(a == b) #true

== 比较的是两个对象的内容是否相等,即内存地址可以不一样,内容一样就可以了。这里比较的并非是同一片叶子,可能叶子的种类或者脉络相同就可以了。默认会调用对象的 __eq__()方法。

python面向对象基础(三)内置方法 __xx__的更多相关文章

  1. Python面向对象编程及内置方法

    在程序开发中,要设计一个类,通常需要满足以下三个要求: [1]类名 这类事物的名字,满足大驼峰命名法 [2]属性 这类事物具有什么样的特征 [3]方法 这类事物具有什么样的行为 定义简单的类: 定义只 ...

  2. python面向对象 : 反射和内置方法

    一. 反射 1. isinstance()和issubclass() isinstance( 对象名, 类名) : 判断对象所属关系,包括父类  (注:type(对象名) is 类名 : 判断对象所属 ...

  3. python 面向对象反射以及内置方法

    一.反射 什么是反射:可以用字符串的方式去访问对象的属性,调用对象的方法(但是不能去访问方法),python中一切皆对象,都可以使用放射. 反射的四种方法: hasattr:hasattr(objec ...

  4. python 面向对象 类的内置方法

    判断是不是类cls的对象 class A: pass a = A() print(isinstance(a,A)) 判断类sub是不是super的子类 class A: pass class B(A) ...

  5. python面向对象--类的内置方法

    #isinstance(obj,cls)判断obj是否是类cls的实例 #issubclass(cls,cls1)判断cls是否是cls1的子类或派生类 class Foo: pass class B ...

  6. Python 数据类型常用的内置方法(三)

    目录 Python 数据类型常用的内置方法(三) 1.列表内置方法 1.sort():升序 2.reverse():颠倒顺序 3.列表比较运算 2.字典内置方法 1.对Key的操作 2.len( )- ...

  7. 铁乐学python_day24_面向对象进阶1_内置方法

    铁乐学python_day24_面向对象进阶1_内置方法 题外话1: 学习方法[wwwh] what where why how 是什么,用在哪里,为什么,怎么用 学习到一个新知识点的时候,多问问上面 ...

  8. Python 数据类型常用的内置方法(一)

    目录 Python 数据类型常用的内置方法 1.整型 int 2.浮点型 float 字符串转浮点型: 3.字符串 str 多种类型转字符型: 索引 切片 len( )方法:统计字符串长度/个数 移除 ...

  9. Python 数据类型常用的内置方法(二)

    目录 Python 数据类型常用的内置方法(二) 1.字符串类型常用内置方法 1.upper.lower.isupper.islower 2.startswith.endswith 3.format ...

  10. Python之路(第二十九篇) 面向对象进阶:内置方法补充、异常处理

    一.__new__方法 __init__()是初始化方法,__new__()方法是构造方法,创建一个新的对象 实例化对象的时候,调用__init__()初始化之前,先调用了__new__()方法 __ ...

随机推荐

  1. 2019icpc南京网络赛

    B. super_log(扩展欧拉函数) 题意:求aa...(b个a)模M的值. 思路:递归用欧拉函数求解,我们知道欧拉降幂公式: 如果讨论b和φ(p)的关系会很麻烦,网上证明了一种精妙的方法,只需重 ...

  2. 数据去重 -uniq

    也是经常和管道 一起操作的. -c  每行出现的次数 -d  仅仅显示重复行 -u  仅仅显示不重复行 -i  忽略大小写 注: 在对字母进行去重的时候, 一定要先对文件进行排序之后,去重的功能才可以 ...

  3. python虚拟环境的的使用

    基于创建虚拟环境 virtualenv 安装 pip3 install virtualenv 通过virtulaenv创建虚拟环境 virtualenv luffycity --python=C:\P ...

  4. 老贾的幸福生活day03 之思维导图

    思维导图 层级关系 从大范围到具体 编程语言 ​ 编译型 ​ C ​ C++ ​ ...... ​ 解释型 ​ python php ​ ......... python ​ 基础语法 ​ 基础数据类 ...

  5. Mysql-Sqlalchemy-多表操作

    import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declar ...

  6. Java 概述和编程基础

    First of all,Java概述: 类是Java程序设计的基石和基本单元: main()方法是程序的入口,它是共有的.静态的,参数String[] args表示一个字符串数组可以传入该程序,用来 ...

  7. 01docker基本概念

    docker基本概念 官方文档URL:https://docs.docker.com/ 1.Docker的构想是要实现"Build, Ship and Run Any App, Anywhe ...

  8. 4-Perl 数据类型

    1.Perl 数据类型Perl 是一种弱类型语言,所以变量不需要指定类型,Perl 解释器会根据上下文自动选择匹配类型.Perl 有三个基本的数据类型:标量.数组.哈希.以下是这三种数据类型的说明:1 ...

  9. Eclipse怎么改变@author 姓名

    1 点击windows  然后选择 点击进去选择搜索code Templates  点击选择出现下面的页面 点开comments,里面有给方法,变量 ,类等加注释设置的模板 如:点击Methods  ...

  10. (一)初识JavaFX

    JavaFX是一个强大的图形和多媒体处理工具包集合,它允许开发者来设计.创建.测试.调试和部署富客户端程序,并且和Java一样跨平台. JavaFX应用程序 由于JavaFX库被写成了Java API ...