Python进阶之其他常见问题

一.函数的闭包

函数闭包(Closure):满足函数嵌套, 在一个内部函数里,对在外部作用(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包

def foo():
    l = []
    d = {}
    def bar(i):
        # nonlocal 声明非本层的局部变量
        nonlocal l, d
        l.append(i)
        d[i] = i
#        print(locals())  # locals()字典打印所有局部变量
        return l,d
    return bar

f1 = foo()
f2 = foo()

# 说出下列语句执行结果
f1(1)         # ([1], {1: 1})
f1(2)        # 先f1(1)在f1(2)结果为 ([1, 2], {1: 1, 2: 2}) 由于内部函数使用了列表和字典,使得l和d无法被释放
f2(3)         # ([3], {3: 3})
  • 作用域

声明全局变量: global
声明非本层的 局部变量 : nonlocal
查看全局变量: globals()
查看局部变量: locals()
查看变量: vars([object]) # 不传参数相当于 locals(), 传入对象后, 会得到 object.__dict__

二.实例方法,类方法和静态方法

  • 实例方法:

通过实例调用
可以引用类内部的任何属性和方法
第一个参数是self
它表示一个具体的实例本身

  • 类方法(classmethod)

无需实例化
可以调用类属性和类方法
无法取到普通的成员属性和方法
第一个参数是cls,表示类本身
使用装饰器@classmethod
它表示当前类本身

  • 静态方法(staticmethod)

无需实例化
无法取到类内部的任何属性和方法, 完全独立的一个方法
无需传任何参数
实例对象和类对象都可以调用
使用装饰器@staticmethod
可以理解为,静态方法是个独立的、单纯的函数

具体代码辨析(https://blog.csdn.net/helloxiaozhe/article/details/79940321)

class Test(object):
    x = 123

    def __init__(self):
        self.y = 456

    def bar1(self):
        print('i am a method')

    @classmethod
    def bar2(cls):
        print('i am a classmethod')

    @staticmethod
    def bar3():
        print('i am a staticmethod')

    def foo1(self):
        print(self.x)
        print(self.y)
        self.bar1()
        self.bar2()
        self.bar3()

    @classmethod
    def foo2(cls):
        print(cls.x)
#         print(cls.y) # 会报错
#         cls.bar1() # 会报错,因为bar1是实例方法. 得通过self.bar1
        cls.bar2()
        cls.bar3()

    @staticmethod
    def foo3(obj):
        print(obj.x)
        print(obj.y)
        obj.bar1()
        obj.bar2()
        obj.bar3()

t = Test()
# t.foo1()
# t.foo2()
t.foo3(t)

out:123
456
i am a method
i am a classmethod
i am a staticmethod

三. 继承相关问题

  • 多态
class Animal:
    def run(self):
        print('animal running')

class Lion(Animal):
    def run(self):
        print('lion running')

class Tiger(Animal):
    def run(self):
        print('tiger running')

class LionTiger(Lion, Tiger):
    pass

cub = LionTiger()
cub.run()
# 这就是多态.
isinstance(cub, Lion)
isinstance(cub, Tiger)
out: lion running
      True

# 继承链
LionTiger.mro()
out:[__main__.LionTiger, __main__.Lion, __main__.Tiger, __main__.Animal, object]

LionTiger.__mro__
out:(__main__.LionTiger, __main__.Lion, __main__.Tiger, __main__.Animal, object)

语法:isinstance(object,type)
作用:来判断一个对象是否是一个已知的类型。
其第一个参数(object)为对象,第二个参数(type)为类型名(int...)或类型名的一个列表((int,list,float)是一个列表)。其返回值为布尔型(True or flase)

  • 多继承

在使用继承的时候,尽量使用Mixin去组合功能.
方法和属性的继承顺序: Cls.mro()
菱形继承问题

继承关系示意
菱形继承
     A.foo()
   /   \
  B     C.foo()
   \   /
     D.mro()  # 方法的继承顺序,由 C3 算法得到

super执行父类的代码的时候是遵循继承链(mro)来做的
执行父类方法的时候,最好使用super()

class A:
    def __init__(self):
        print('enter A')
        self.x = 111
        print('exit A')

class B(A):
    def __init__(self):
        print('enter B')
        self.y = 222
#         A.__init__(self)
        super().__init__()
        print('exit B')

class C(A):
    def __init__(self):
        print('enter C')
        self.z = 333
#         A.__init__(self)
        super().__init__()
        print('exit C')

class D(B, C):
    def __init__(self):
        print('enter D')
#         B.__init__(self)
#         C.__init__(self)
        super().__init__()
        print('exit D')

d = D()
out:enter D
enter B
enter C
enter A
exit A
exit C
exit B
exit D

你可能感兴趣的:(Python进阶之其他常见问题)