面向对象
把对象作为基本单元,把对象抽象成类,包括成员(即类的属性)和方法(即类的行为)。从而实现代码的封装和可复用性。
优先使用组合而非继承:组合就是使用其他类实例作为自己的一个属性,继承就是子类继承父类的方法和属性。当然继承要有基本的继承关系才是真正的思路。
类变量和实例变量.
类方法和静态方法的区别:
1.都可以通过class.method的方式调用
2.classmethod的一个参数是cls(可以自定),可以引用当前类对象
3.staticmethod相当于把普通函数放在了类里面,一般里面是没有用到实例变量和类变量,包括类方法也没有用到,放在里面是为了更好的组织代码和类的封装性。
元类
元类是创建类的类。元类允许我们控制类的生成,比如修改类的属性。元类继承type
装饰器
应用场景:“对修改是封闭的,对拓展是开放的”。当需求变更时,尽量不要改变原有函数,方法的实现。
例如你想给某些函数测试运行时间,如果你在那些函数里面修改代码,无疑是大大的工作量。如果使用装饰器,就相对简单而且复用性好,不需要改动那些函数原有代码。下面是个简单的例子,如果有多个函数f1,f2,f3....,如果直接把测试时间的代码写到对应函数里面会相当复杂,而提取出来利用python一切皆对象的特性把函数当做参数传入,就化繁为简,相当优雅。
def f1():
print("this is a function 1")
def f2():
print("this is a function2")
def print_current_time(func):
print(time.time())
func()
print_current_time(f1)
print_current_time(f2)
但是上面的写法很不好,它把打印时间的语句跟函数本身割裂开来,只是相当于在每个函数前面多加一条打印语句而已。因此,装饰器语法就派上用处了。以下是装饰器实现,可以看到,装饰器封装性更好,而且原有函数名没有改变,这样就避免了在其他代码重新替换f1.
def decorator(func):
def wrapper():
print(time.time())
func()
return wrapper
f1 = decorator(f1) # 这里返回的是wrpper函数
f1()
# f1,f2假如有参数,可以通过wrapper传入,因为最后其实是wrapper调用
# 而wrapper实现了在f1,f2前面和后面增加代码的作用
# 外层的decorator只是一个传递f1的作用
def decorator(func):
def wrapper(*args,**kwargs): # f1和f2的参数个数不同,必须要*args,**kwargs才能兼容
print(time.time())
func(*args,**kwargs)
return wrapper
“可以接受定义的复杂,不能接受调用的复杂”,python提供装饰器的语法糖@
def decorator(func):
def wrapper(*args,**kwargs): # 必须要*args,**kwargs才能兼容所以参数情况
print(time.time())
func(*args,**kwargs)
return wrapper
@decorator # 替代了f1 = decorator(f1),封装性更好
def f1():
print("this is a function 1")
f1() # 直接还是f1,但是是更新版的,没有改变f1的调用方式,也无需更改其他地方f1
总结:有了@的语法糖,可以给原来的函数和方法上加更多的功能,而且不会改变原来函数的调用方式,减少更改!这才是装饰器的优势。但是装饰器是不能改变函数里面的代码的,只能用于对函数外面增加代码。