class Testa:
pass class Testb(object):
pass if __name__ == '__main__':
print 'testb = ',dir(Testb)
print '\n'
print 'testa = ',dir(Testa)

运行结果:

testb = ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

testa = ['__doc__', '__module__']

class A(object):
"""
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(self):
print 'a static func.' @classmethod
def class_test(self):
print 'a calss func.' obj = A()
print A.__dict__
print obj.__dict__

运行结果:

{'a': 0, '__module__': '__main__', 'b': 1, 'class_test': <classmethod object at 0x021FF510>, '__dict__': <attribute '__dict__' of 'A' objects>, '__init__': <function __init__ at 0x01E19DB0>, 'test': <function test at 0x022044B0>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': '\n Class A.\n ', 'static_test': <staticmethod object at 0x021FF4D0>}

{'a': 2, 'b': 3}

由此可见,类和实例分别拥有自己的__dict__

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

对象的__dict__中存储了一些self.xxx的一些东西

2、Python里什么没有__dict__属性

  虽然说一切皆对象,但对象也有不同,就好比不是每个人的女朋友都是一个人一样,一些内置的数据类型是没有__dict__属性的,如下:

num = 3
ll = []
dd = {}
print num.__dict__
print ll.__dict__
print dd.__dict__

当我们运行这样的代码时,解释器就会告诉我们

Traceback (most recent call last):
File "f:\python\test.py", line 54, in <module>
print num.__dict__
AttributeError: 'int' object has no attribute '__dict__' Traceback (most recent call last):
File "f:\python\test.py", line 55, in <module>
print ll.__dict__
AttributeError: 'list' object has no attribute '__dict__' Traceback (most recent call last):
File "f:\python\test.py", line 56, in <module>
print dd.__dict__
AttributeError: 'dict' object has no attribute '__dict__'

int, list, dict等这些常用的数据类型是没有__dict__属性的,其实这是可预料的,就算给了它们dict属性也没啥用,毕竟它们只是用来做数据容器的。

3、发生继承时候的__dict__属性

  子类有自己的__dict__, 父类也有自己的__dict__,子类的全局变量和函数放在子类的dict中,父类的放在父类dict中。

class Parent(object):
a = 0
b = 1 def __init__(self):
self.a = 2
self.b = 3 def p_test(self):
pass class Child(Parent):
a = 4
b = 5 def __init__(self):
super(Child, self).__init__()
# self.a = 6 #重写父类的成员变量
# self.b = 7 def c_test(self):
pass def p_test(self):
pass p = Parent()
c = Child()
print Parent.__dict__
print Child.__dict__
print p.__dict__
print c.__dict__

运行结果:

{'a': 0, '__module__': '__main__', 'b': 1, '__dict__': <attribute '__dict__' of 'Parent' objects>, 'p_test': <function p_test at 0x021B4530>, '__weakref__': <attribute '__weakref__' of 'Parent' objects>, '__doc__': None, '__init__': <function __init__ at 0x00879DB0>}
{'a': 4, 'c_test': <function c_test at 0x021B44F0>, '__module__': '__main__', 'b': 5, 'p_test': <function p_test at 0x021B4570>, '__doc__': None, '__init__': <function __init__ at 0x021B4470>}
{'a': 2, 'b': 3}
{'a': 2, 'b': 3}

  1)上段输出结果中,用红色字体标出的是类变量和函数,由结果可知,每个类的类变量、函数名都放在自己的__dict__中

  2) 再来看一下实力变量的__dict__中,由蓝色字体标识,父类和子类对象的__dict__是公用的

class Borg(object):
__shared_state = {} #子类和父类共享这个变量,导致输出的结果是一样的,具有迷惑性 def __init__(self):
self.__dict__ = self.__shared_state
self.state = 'Init' def __str__(self):
return self.state class YourBorg(Borg):
pass if __name__ == '__main__':
rm1 = Borg()
rm2 = Borg() rm1.state = 'Idle'
rm2.state = 'Running' print('rm1: {0}'.format(rm1))
print('rm2: {0}'.format(rm2))

输出结果:

rm1: Running
rm2: Running

上面这一段代码,乍看挺神奇的,Borg 的各个实例共享了state。实现起来也很巧妙,利用了__dict__。 我们知道,python中__dict__存储了该对象的一些属性。类和实例分别拥有自己的__dict__,且实例会共享类的__dict__。

这里有一个我一直以来都搞混的知识点,在__init__ 中声明的变量 ,以及在方法体之外声明的变量分别是在哪里。很简单的测试就能得到,在__init__中,self.xxx = xxx会把变量存在实例的__dict__中,仅会在该实例中能获取到,

而在方法体外声明的,会在class的__dict__中。

总结:

  1) 内置的数据类型没有__dict__属性

  2) 每个类有自己的__dict__属性,就算存着继承关系,父类的__dict__ 并不会影响子类的__dict__

  3) 对象也有自己的__dict__属性, 存储self.xxx 信息,父子类对象公用__dict__

__xxxitem__:使用 [''] 的方式操作属性时被调用

__setitem__:每当属性被赋值的时候都会调用该方法,因此不能再该方法内赋值 self.name = value 会死循环

__getitem__:当访问属性时会调用该方法

__delitem__:当删除属性时调用该方法

python 运算符重载__getitem__和__setitem__

class Indexer:
def __getitem__(self, index): #重载索引,对于实例的索引运算,会自动调用__getitem__
return index**2 x = Indexer()
print(x[3]) class Indexer2:
data=[1,2,3,4,5]
def __getitem__(self, index): #重载索引,对于实例的索引运算,会自动调用__getitem__
print '__getitem__'
return self.data[index]
def __setitem__(self, index, value): #重载索引赋值,对于实例的索引赋值,会自动调用__setitem__
print 'setitem:'
self.data[index]=value
def __index__(self):
print '__index__'
return 255 x=Indexer2()
print(x[0])
print x[::-1]
print(x[1:])
print(x[2:4])
print(bin(x), bin(255))
print(('a'*256)[x])
x[0] = 102
print x
exit(0)

运行结果:

9
__getitem__
1
__getitem__
[5, 4, 3, 2, 1]
__getitem__
[2, 3, 4, 5]
__getitem__
[3, 4]
__index__
('0b11111111', '0b11111111')
__index__
a
setitem:
<__main__.Indexer2 instance at 0x022C3D50>

python中 __setitem__(),__getitem__()

class Person:
#将对象当作字典操作,设置键值对时会触发该方法
def __setitem__(self, key, value):
print(key,value)
self.__dict__[key]=value #将对象当作字典操作,根据键获取值时会触发该方法 def __getitem__(self, item):
print(item)
return self.__dict__.get(item) #将对象当作字典操作,删除指定的键值对时自动触发 def __delitem__(self, key):
del self.__dict__[key] xiaoming = Person()
xiaoming['name'] = '小宏'
print(xiaoming.__dict__)
print(xiaoming['name'])
del xiaoming['name']

运行结果:

('name', '\xe5\xb0\x8f\xe5\xae\x8f')
{'name': '\xe5\xb0\x8f\xe5\xae\x8f'}
name
小宏

__setitem__(self,key,value):

这个方法应该以与键相关联的方式存储值,以便之后能够使用__setitem__来获取。当然,这个对象可变时才需要实现这个方法。

class Tag:
def __init__(self):
self.change = {'python': 'This is python',
'php': 'PHP is a good language'} def __getitem__(self, item):
print('调用getitem')
return self.change[item] def __setitem__(self, key, value):
print('调用setitem')
self.change[key] = value a = Tag()
print(a['php'])
a['php'] = 'PHP is not a good language'
a['ruby'] = 'Ruby is not a good language'
print(a['php'])
print(a['ruby'])
print a.__dict__
exit(0)

运行结果:

调用getitem
PHP is a good language
调用setitem
调用setitem
调用getitem
PHP is not a good language
调用getitem
Ruby is not a good language
{'change': {'python': 'This is python', 'php': 'PHP is not a good language', 'ruby': 'Ruby is not a good language'}}

__delitem__和__delattr__

class Foo:
def __init__(self,name):
self.name=name
def __getitem__(self, item):
if item == 1:
print('hahaha')
# print(self.__dict__[item])
def __setitem__(self, key, value):
self.__dict__[key]=value
def __delitem__(self, key):
print('del obj[key]时,我执行')
self.__dict__.pop(key)
def __delattr__(self, item):
print('del obj.key时,我执行')
self.__dict__.pop(item) f1 = Foo('sb')
#访问属性的方式变了
#对象名.属性
f1=Foo('sb')
f1['age']=18 #给f1添加一个属性
del f1['age'] #删除属性
# f1.name
print(f1['name']) f1.__dict__['age'] = 18
f1['age1']=19
del f1.age1 #删除属性 f1['name']='alex'
print(f1.__dict__)
exit(0)

输出结果:

del obj[key]时,我执行
None
del obj.key时,我执行
{'age': 18, 'name': 'alex'}

使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。而如果要保持Key的顺序,可以用OrderedDict

注意,OrderedDict的Key会按照插入的顺序排列,不是Key本身排序:

OrderedDict可以实现一个FIFO(先进先出)的dict,当容量超出限制时,先删除最早添加的Key:

from collections import OrderedDict

class LastUpdatedOrderedDict(OrderedDict):

    def __init__(self, capacity):
super(LastUpdatedOrderedDict, self).__init__()
self._capacity = capacity def __setitem__(self, key, value):
containsKey = 1 if key in self else 0
if len(self) - containsKey >= self._capacity:
last = self.popitem(last=False)
print 'remove:', last
if containsKey:
del self[key]
print 'set:', (key, value)
else:
print 'add:', (key, value)
OrderedDict.__setitem__(self, key, value) # test
d = LastUpdatedOrderedDict(capacity=3) d['A'] = 100
d['B'] = 200
d['C'] = 300
d['D'] = 400
d['E'] = 500
print d

运行结果:

add: ('A', 100)
add: ('B', 200)
add: ('C', 300)
remove: ('A', 100)
add: ('D', 400)
remove: ('B', 200)
add: ('E', 500)
LastUpdatedOrderedDict([('C', 300), ('D', 400), ('E', 500)])

python中__len__

#coding=utf-8
class A: def __init__(self):
self.a = 1
self.b = 2 def fun(self):
pass def __len__(self):
return len(self.__dict__) #返回的是对象自身的长度 a = A()
print(len(a)) #
exit(0)

_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)) #当在外部使用hash()这种方法实际上就是在内部调用 __hash__这个方法
exit(0)

_EQ__

#coding=utf-8
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) #在外部执行==实际上就是在内部调用 __eq__方法
exit(0)

__call__

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

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

#coding=utf-8
class Foo: def __init__(self):
pass def __call__(self, *args, **kwargs):
print('__call__') obj = Foo() # 执行 __init__
obj() # 执行 __call__
exit(0)

python __setitem__ 和 __setattr__关于无限递归

对于__setattr__如果用如下的定义
def __setattr__(self,name,value):
  self.name=value 
它在出现类似self.a=b的赋值语句时会调用__setattr__并在函数中继续进行同样的赋值操作从而引起无限递归,也就是触发调用__setattr__的条件是遇到self.a=b这样的语句

但对于__setitem__
def __setitem__(self,key,value): 
  self.__dict__[key]=value
如果定义了一个实例s,要使用序列的方法__setitem__,自然s会成一个字典,而如果我使用s[a]=b的语句修改字典的键的值时为何不会再在__setitem__中继续将a和b作为key和value进行修改赋值从而出现无限递归?
触发调用__setitem__的条件应该是类似s[a]=b还是别的什么语句吗?

 
def __setitem__(self,key,value):
self[key]=value #以这种方式则会触发无限递归 def __setitem__(self,key,value):
self.__dict__[key]=value #这种则不会,它是以修改对象内置字典的键的值的方式来修改对象的属性值

参考自:

https://blog.csdn.net/qq_42467563/article/details/82974285

https://www.jianshu.com/p/cf8450b4b537

https://www.cnblogs.com/alvin2010/p/9102344.html

https://blog.csdn.net/xhw88398569/article/details/48690163

python中dir,__dict__ , __setitem__(),__getitem__()的更多相关文章

  1. python中dir(),__dict__

    dir()是python的一个函数, dir()函数如果接受的参数是一个类,则返回这个类所有的类变量和方法 dir()函数如果接收的参数是一个类的实例,则返回这个实例所有的实例变量,对应的类的类变量, ...

  2. python 中dir()和__dict__的区别

    Python __dict__与dir() 出处(http://blog.csdn.net/lis_12/article/details/53521554). Python下一切皆对象,每个对象都有多 ...

  3. python中的__dict__和dir()的区别

    Python下一切皆对象,每个对象都有多个属性(attribute),Python对属性有一套统一的管理方案. __dict__与dir()的区别: dir()是一个函数,返回的是list: __di ...

  4. Python中dir()与help()的使用

    python内置了很多内置函数.类方法属性及各种模块.当我们想要当我们想要了解某种类型有哪些属性方法以及每种方法该怎么使用时,我们可以使用dir()函数和help()函数在python ide交互式模 ...

  5. python中的__dict__,__getattr__,__setattr__

    python class 通过内置成员dict 存储成员信息(字典) 首先用一个简单的例子看一下dict 的用法 class A(): def __init__(self,a,b): self.a = ...

  6. 【Python】python中的__dict__,__getattr__,__setattr__

    Python class 通过内置成员__dict__ 存储成员信息(字典) 首先用一个简单的例子看一下__dict__ 的用法 class A(): def __init__(self,ax,bx) ...

  7. python中__dict__和dir()

    转自:http://www.cnblogs.com/ifantastic/p/3768415.html 首先需要知道的是,dir() 是 Python 提供的一个 API 函数,dir() 函数会自动 ...

  8. python中__dict__与dir()的区别

    在python中__dict__与dir()都可以返回一个对象的属性,区别在于: __dict__是对象的一个属性,而dir()是一个built-in的方法: __dict__返回一个对象的属性名和值 ...

  9. python 魔法方法之:__getitem__ __setitem__ __delitem__

    h2 { color: #fff; background-color: #7CCD7C; padding: 3px; margin: 10px 0px } h3 { color: #fff; back ...

随机推荐

  1. python实现查找算法

    搜索是在一个项目集合中找到一个特定项目的算法过程.搜索通常的答案是真的或假的,因为该项目是否存在. 搜索的几种常见方法:顺序查找.二分法查找.二叉树查找.哈希查找 线性查找线性查找就是从头找到尾,直到 ...

  2. MyBatis_动态sql_foreach_mysql下foreach批量插入的两种方式

    方法1: 笔记要点出错分析与总结工程组织数据库组织0.重新修改Bean类    修改1.定义接口 //批量插入 public void addEmps(@Param("emps") ...

  3. __str__()方法

    只要定义了__str__(self)方法,那么就会打印从这个方法中return的数据 class Car: def __init__(self, newWheelNum, newColor): sel ...

  4. js中使用Switch

    语法 switch(n) { case 1: 执行代码块 1 break; case 2: 执行代码块 2 break; default: n 与 case 1 和 case 2 不同时执行的代码 } ...

  5. 14 Vue列表渲染

    列表渲染 用 v-for 把一个数组对应为一组元素(for循环) 我们可以用 v-for 指令基于一个数组来渲染一个列表. v-for 指令需要使用 item in items 形式的特殊语法, 其中 ...

  6. Time Intersection

    Description Give two users' ordered online time series, and each section records the user's login ti ...

  7. 定时器 间隔调用setInterval

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. docker学习(四)

    一.Docker数据管理 在容器中管理数据主要有两种方式:1.数据卷(Data volumes)2.数据卷容器(Data volume containers) 1.数据卷数据卷是一个可供一个或多个容器 ...

  9. [RxJS] Convert a Node.js style callback to Observable: bindNodeCallback

    It's just like bindCallback, but the callback is expected to be of type callback(error, result). imp ...

  10. iptables 相关命令

    1. 清除已有iptables规则 iptables -F iptables -X iptables -Z 2. 开放指定的端口(添加规则) iptables -A INPUT -s 127.0.0. ...