class Foo(object):
def __init__(self):
print("init")
def __call__(self, *args, **kwargs):
print("call")
def __getattr__(self, item):
print("getattr", item)
def __setattr__(self, key, value):
print(key, value)
def __str__(self):
return "str"
def __repr__(self):
print("repr")
def __add__(self, other):
return other+1
def __getitem__(self, item):
print(item)
def __setitem__(self, key, value):
print(key, value)
def __delitem__(self, key):
print(key)
def __iter__(self):
return iter([1, 2, 3])
def __contains__(self, item):
print(item)
return True
obj = Foo() # 只执行__init__
obj() # 调用 __call__
obj.xx # 调用__getattr__, 把xx当作item传给item
obj.xx = 123 # 调用__setattr__, 把xx当作key,123当作value 传给方法
print(obj) # 调用__str__, 打印返回值
print('%s'%obj) # 走的也是__str__
print(repr(obj)) # 调用__repr__
print('%r'%obj) # 走的是__repr__
print(obj+7) # 调用__add__, 把7当作other传给方法
obj['k1'] # 调用__getitem__,k1为item
obj['k1'] = 123 # 调用__setitem__, k1为key.123为value
del obj['k1'] # 调用__delitem__, k1为key
for i in obj: # 调用__iter__, 它必须返回迭代器
print(i)
"x" in obj # 调用__contains__, 打印结果 x
hasattr 可以获得静态属性和类属性,
getattr 和一拿到静态属性和类属性, 拿到的类属性, 就是个函数时,拿的内存地址。当那不存在的属性时,会触发异常,这种情况, 可以设置默认值。
setattr 和更新属性, 不存在时自动创建属性。
class FunctionDemo(object):
name = 'demo'
def do_it(self):
return "123"
obj = FunctionDemo()
print(hasattr(obj, 'name')) # True
print(hasattr(obj, 'do_it')) # True
print(getattr(obj, 'name')) # demo
print(getattr(obj, 'do_it')) # 内存地址
# print(getattr(obj, 'nn')) 找没有的属性会报错
print(getattr(obj, 'nn', 'lala')) # 如果没没拿到, 就拿默认值
setattr(obj, "nn", 66)
print(getattr(obj, 'nn')) # 66
class Base(object):
def func(self):
print("父类")
class Foo(Base):
def func1(self):
super(Foo, self).func() # 按顺序执行到父类
# 也可直接super().func(), 不加会默认加参数
Base.func(self) # 直接执行父类
print("子类")
obj = Foo()
obj.func1()
# 父类
# 父类
# 子类
class Base(object):
def func(self):
print("base")
super(Base, self).func1()
class Bar(object):
def func1(self):
print("Bar")
class Foo(Base, Bar):
pass
obj = Foo()
obj.func()
# base
# Bar
瞎鸡解析:
obj.func() 调用func,首先会在自己(Foo)里找有没有func,然后再按继承顺序从最近的Base里找func,再从Bar找。
而super 正是按这一顺序执行的,
首先func在Foo里没找到,从Base里找到了func,执行print,遇到super,super按下一顺序找到Bar, .func1执行里面的print。
而上面的第二个也是这样,先从Foo里找func1, 再从Foo的父类Base找, super按下依顺序找到Base,再.func执行里面的print。
下面是几个例子,说明py3的类继承的顺序,是广度优先的,而py2的经典类是深度优先的。
例一:说明super是广度优先的
class A(object):
def func(self): # 9
print('a') # 10
class B(A):
def func(self): # 5
super(B, self).func() # 6
print('b') # 12
class C(A):
def func(self): # 7
super(C, self).func() # 8
print('c') # 11
class D(B, C):
def func(self): # 3
super(D, self).func() # 4
print('d') # 13
d = D() # 1
d.func() # 2
# a
# c
# b
# d
例二:
class A(object):
def func(self):
print('a')
class B(A):
def func(self):
print('b')
class C(A):
def func(self):
print('c')
class D(B, C):
print('d')
print(D.mro())
# [, , , , ]
例一,例二图
例三:
B继承A,C继承E,D继承BC
例四:复杂的继承关系
class Foo(object):
__slots__ = ('name', ) # 只能 .出name
def __init__(self):
self.name = "aki"
obj = Foo()
# obj.age = 19 # 因为 上面设置了 __slots__ = ('name', ) 所以会报错,
print(obj.name)
# print(obj.age)
__call__
""" __call__ """
class Foo(object):
def __init__(self, a): # 初始化
print(a)
print("pk")
def __call__(self, *args, **kwargs): # 可调用
print(args, kwargs)
obj = Foo(123) # 实例化 可以传参数被init使用
obj(12, 34, 344, a=678) # 可以传参数变成一个函数
# 123
# pk
# (12, 34, 344) {'a': 678}
__new__
"""__new__"""
class Foo(object):
def __init__(self):
print("init")
def __new__(cls, *args, **kwargs): # cls 为一个类, 最先执行__new__,构造一个实例传给__init__
print("new")
return super(Foo, cls).__new__(cls) # 没有这句只执行__new__,
# return object.__new__(cls, *args, **kwargs)
Foo()
# new
# init
注意: __new__返回已经实例化的对象或不返回,不会执行__init__
obj = 123
class Foo(object):
def __init__(self):
print("init")
def __new__(cls, *args, **kwargs): # cls 为一个类, 最先执行__new__,构造一个实例传给__init__
print("new")
return obj # 不会执行__init__, 没return 更不会执行
Foo()
# new
关于__new__和 __init__
# 第一种
class Foo(object):
a = 123
def func(self):
return 123
# 第二种
Foo = type('Foo', (object,), {'a': 123, 'func': lambda self: 123})
# Foo继承object,
obj = Foo()
print(obj.func())
print(obj.a)
class Foo(object):
def __init__(self, name, age):
self.name = name
self.__age = age # 私有方法不能随意调用
def func(self):
print(self.__age) # 可以调用
obj = Foo("XX", 33)
obj.func() # 可以打印__age
# print(obj.__age)
print(obj._Foo__age) # 硬拿也可以拿到
# 如果再来个类继承这个Foo, 继承的子类也是不能调用私有方法的
class Foo(object):
def __init__(self):
print("init")
def __enter__(self):
print('进来')
def __exit__(self, exc_type, exc_val, exc_tb):
print('出来')
obj = Foo()
with obj: # 自动触发__enter__
print('中间')
# 执行前自动触发__enter__,执行自己,再执行__exit__
# init
# 进来
# 中间
# 出来
class A(object):
def __init__(self):
self.state = False
def __enter__(self):
self.state = True
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.state = False
obj = A()
print(obj.state)
with obj:
print(obj.state)
print(obj.state)
# 注意,_enter_方法必须返回一个对象,可以是自身,也可以是其他的对象。
# False
# True
# False
注意,_enter_方法必须返回一个对象,可以是自身,也可以是其他的对象。
exc_type : 异常类型
exc_val : 异常值
exc_tb : 异常回溯追踪
from contextlib import contextmanager
@contextmanager
def my_open(path, mode):
f = open(path, mode)
yield f
f.close()
Python 还提供了一个 contextmanager 的装饰器,更进一步简化了上下文管理器的实现方式。通过 yield 将函数分割成两部分,yield 之前的语句在 __enter__ 方法中执行,yield 之后的语句在 __exit__ 方法中执行。紧跟在 yield 后面的值是函数的返回值。
class Foo(object):
def send(self):
raise NotImplementedError('子类没有实现这个方法')
class Demo(Foo):
def send(self):
print("子类要有这个方法,要不就报错")
obj = Demo()
obj.send() # 实例化时不会报错,只在.send时才会报错
import abc
class Base(metaclass=abc.ABCMeta):
@abc.abstractmethod
def send(self):
pass
def func(self):
print('func')
class Foo(Base):
def send(self):
print("o")
obj = Foo() # Foo 如果没send, 实例化时就会报错
obj.send()
一个类的属性是另一个类的对象
class Course(object):
def __init__(self, name):
self.name = name
python = Course('python')
class Classes(object):
def __init__(self, name, course):
self.name = name
self.course = course
py = Classes('小葵花大班', python) # python 是上面的实例化,即是对象
print(py.course.name)
# python
class A(object):
_instance = None
def __init__(self, name):
self.name = name
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = object.__new__(cls)
return cls._instance
else:
return cls._instance
aki = A('aki')
desky = A('desky')
print(aki)
print(desky)
print(aki.name)
print(desky.name)
# <__main__.A object at 0x000001AF6E370550>
# <__main__.A object at 0x000001AF6E370550>
# desky
# desky
单例模式, 一个类始终只有一个实例,第一次来的时候创建一个实例, 再来的时候用之前第一次创建的实例。
python中,一切都是对象,比如一个数字、一个字符串、一个函数。对象是类(class)的是实例,类(class)也是对象,是type的实例。type对象本身又是type类的实例,因此我们称type为metaclass(中文元类)。
通俗地说就是说,python3中,所有的类都是新式类,都继承自object,而object又都继承自type,所有的class是object的实例,而object是type的实例。
>>> age = 24
>>> age.__class__
>>> name = 'bob'
>>> name.__class__
>>> age.__class__.__class__
>>> name.__class__.__class__
还可以自定制matclass
class ListMetaclass(type):
def __new__(cls, name, bases, attrs):
attrs['add'] = lambda self, value: self.append(value)
return type.__new__(cls, name, bases, attrs)
class MyList(list):
__metaclass__ = ListMetaclass # 指示使用ListMetaclass来定制类