python面试充电(3)面向对象、设计模式

面向对象

把对象作为基本单元,把对象抽象成类,包括成员(即类的属性)和方法(即类的行为)。从而实现代码的封装和可复用性。

优先使用组合而非继承:组合就是使用其他类实例作为自己的一个属性,继承就是子类继承父类的方法和属性。当然继承要有基本的继承关系才是真正的思路。

类变量和实例变量.

类方法和静态方法的区别:

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.

扫描二维码关注公众号,回复: 6208287 查看本文章
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

总结:有了@的语法糖,可以给原来的函数和方法上加更多的功能,而且不会改变原来函数的调用方式,减少更改!这才是装饰器的优势。但是装饰器是不能改变函数里面的代码的,只能用于对函数外面增加代码。

猜你喜欢

转载自blog.csdn.net/weixin_37143690/article/details/90094517