python一切皆对象。
#!/usr/bin/env python
#-*- coding = utf-8 -*-
'''
@Author: hszhang@foxmail.com
@Date : 2019/4/26
@Desc : Invest entry(main)
'''
# 新式类
class ClassA(object):
num_A = 1
def foo_A(self):
pass
def __str__(self):
return 'this is ClassA'
class ClassB(ClassA):
num_B = 2
def __init__(self, name='ClassB'):
self.name = name
def foo_B(self):
pass
- 查看类的属性
print(dir(ClassA))
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'foo_A', 'num_A']
- 基类的属性
print(ClassA.__dict__)
输出
{
'__module__': '__main__',
'num_A': 1,
'foo_A': <function ClassA.foo_A at 0x00000000022A4620>,
'__str__': <function ClassA.__str__ at 0x00000000022A46A8>,
'__dict__': <attribute '__dict__' of 'ClassA' objects>,
'__weakref__': <attribute '__weakref__' of 'ClassA' objects>,
'__doc__': None
}
print(ClassB.__dict__) # 类对象的__dict__不包含基类的属性
{
'__module__': '__main__',
'num_B': 2,
'__init__': <function ClassB.__init__ at 0x00000000028C4730>,
'foo_B': <function ClassB.foo_B at 0x00000000028C47B8>,
'__doc__': None
}
- object.setattr(self, name, value)
实例对象通过instanceA.__setattr__赋值,被赋值的属性和值会存入实例属性字典__dict__中。
class ClassA(object):
def __init__(self, classname):
self.classname = classname
insA = ClassA('ClassA')
print(insA.__dict__)
# {'classname': 'ClassA'}
insA.tag = 'insA'
print(insA.__dict__)
# {'tag': 'insA', 'classname': 'ClassA'}
- object.getattr(self, name)
实例instance通过instance.getattr_访问属性name,只有当属性name没有在实例的__dict__或它构造类的__dict__或基类的__dict__中没有找到,才会调用__getattr_。
如果在__getattr__(self, attr)存在通过self.attr访问属性,会出现无限递归错误。
class ClassA(object):
def __init__(self, classname):
self.classname = classname
def __getattr__(self, attr):
return('invoke __getattr__', attr)
insA = ClassA('ClassA')
print(insA.__dict__)
# {'classname': 'ClassA'}
print(insA.classname) # 实例insA已经有classname属性了,不会调用__getattr__
# ClassA
print(insA.grade) # grade属性没有找到,调用__getattr__
# ('invoke __getattr__', 'grade')
- object.getattribute(self, name)
实例instance通过instance.__getattribute__访问属性name,__getattribute__方法一直会被调用,无论属性name是否追溯到。
如果在__getattribute__(self, attr)方法下存在通过self.attr访问属性,会出现无限递归错误。
- 剖析一下addic的源码
import copy
class Dict(dict):
def __init__(__self, *args, **kwargs):
object.__setattr__(__self, '__parent', kwargs.pop('__parent', None))
object.__setattr__(__self, '__key', kwargs.pop('__key', None))
for arg in args:
if not arg:
continue
elif isinstance(arg, dict):
for key, val in arg.items():
__self[key] = __self._hook(val)
elif isinstance(arg, tuple) and (not isinstance(arg[0], tuple)):
__self[arg[0]] = __self._hook(arg[1])
else:
for key, val in iter(arg):
__self[key] = __self._hook(val)
for key, val in kwargs.items():
__self[key] = __self._hook(val)
def __setattr__(self, name, value):
if hasattr(self.__class__, name):
raise AttributeError("'Dict' object attribute "
"'{0}' is read-only".format(name))
else:
self[name] = value
def __setitem__(self, name, value):
super(Dict, self).__setitem__(name, value)
try:
p = object.__getattribute__(self, '__parent')
key = object.__getattribute__(self, '__key')
except AttributeError:
p = None
key = None
if p is not None:
p[key] = self
object.__delattr__(self, '__parent')
object.__delattr__(self, '__key')
def __add__(self, other):
if not self.keys():
return other
else:
self_type = type(self).__name__
other_type = type(other).__name__
msg = "unsupported operand type(s) for +: '{}' and '{}'"
raise TypeError(msg.format(self_type, other_type))
@classmethod
def _hook(cls, item):
if isinstance(item, dict):
return cls(item)
elif isinstance(item, (list, tuple)):
return type(item)(cls._hook(elem) for elem in item)
return item
def __getattr__(self, item):
return self.__getitem__(item)
def __missing__(self, name):
return self.__class__(__parent=self, __key=name)
def __delattr__(self, name):
del self[name]
def to_dict(self):
base = {}
for key, value in self.items():
if isinstance(value, type(self)):
base[key] = value.to_dict()
elif isinstance(value, (list, tuple)):
base[key] = type(value)(
item.to_dict() if isinstance(item, type(self)) else
item for item in value)
else:
base[key] = value
return base
def copy(self):
return copy.copy(self)
def deepcopy(self):
return copy.deepcopy(self)
def __deepcopy__(self, memo):
other = self.__class__()
memo[id(self)] = other
for key, value in self.items():
other[copy.deepcopy(key, memo)] = copy.deepcopy(value, memo)
return other
def update(self, *args, **kwargs):
other = {}
if args:
if len(args) > 1:
raise TypeError()
other.update(args[0])
other.update(kwargs)
for k, v in other.items():
if ((k not in self) or
(not isinstance(self[k], dict)) or
(not isinstance(v, dict))):
self[k] = v
else:
self[k].update(v)
def __getnewargs__(self):
return tuple(self.items())
def __getstate__(self):
return self
def __setstate__(self, state):
self.update(state)
def setdefault(self, key, default=None):
if key in self:
return self[key]
else:
self[key] = default
return default
- hasattr(object, name)
判断object对象中是否存在name属性,当然对于python的对象而言,属性包含变量和方法;有则返回True,没有则返回False;需要注意的是name参数是string类型,所以不管是要判断变量还是方法,其名称都以字符串形式传参;getattr和setattr也同样;