4 python中深入类和对象

4.python中的类和对象

4.1鸭子类型和多态

鸭子类型字面意思,一个东西看上去像鸭子,那么我们就把他当做鸭子。在函数上的表现为,多个函数能够实现某一个一样的方法,我们就说他们同类。给了例子:

class Doge:
    def quack(self):
        print('i am doge')

class Pig:
    def quack(self):
        print('i am pig')

class Brid:
    def quack(self):
        print('i am brid')

# 首先实例化三个对象
a = Doge()
b = Pig()
c = Brid()

# 然后分别让他们运行同样的方法quack()
for i in [a,b,c]:
    i.quack()

# 输出结果如下:
i am doge
i am pig
i am brid

对于多态而言,根据python语言的特性:多态,封装,继承
多态:对于不同类型的对象可以执行相同的操作
例如:

# python中+
def add(a,b):
    return a+b

print(add(1,2))
print(add('a','b'))

封装:对外部隐藏有关对象工作原理的细节
继承:可基于通用类创建专用类

4.2抽象基类

使用情况:
1.我们在某些情况下希望判定某个对象的类型(需要知道抽象基类)
isinstance()
2.我们需要强制某个子类必须实现某些方法

4.3 使用instance而不是type

is用于判断对象类型是否相同,==判断两个数值是否相同。

4.4 类变量和对象变量

类变量进行修改时,通过类构建的实例的变量相应发生改变;
但是通过实例访问变量时,并对变量进行赋值时,实例变量的值发生变化,重新通过类构造的实例,类的变量并不会发生变化。

4.5 类属性和实例属性以及查找顺序

MRO算法:DFS
对于菱形继承而言,DFS不太可行,改用BFS

C3算法(python属性的查找算法)
菱形继承:

# 菱形继承
class A:
    pass
class B(A):
    pass
class C(A):
    pass
class D(B,C):
    pass

if __name__=='__main__':
    print(D.__mro__)
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

# 新式类
class A:
    pass
class B(A):
    pass
class C:
    pass
class D(C):
    pass
class E(B,D):
    pass
 
if __name__=='__main__':
    print(E.__mro__)
# (<class '__main__.E'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.D'>, <class '__main__.C'>, <class 'object'>)

4.6 静态方法、类方法以及对象方法以及参数

静态方法
我们在一个类中进行相应的操作时定义了一个函数,要求这个函数与实例和所在的类都无关,那么我们需要定义一个静态方法

@staticmethod
def fun():
	pass

相对于静态方法,我们在调用相应的静态方法时,如果静态方法返回了某些值到类对象中,那么我们需要重新写静态的方法,这样显得十分麻烦,因此产生了类方法:

#静态方法
class Name:
   def __init__(self,x):
       self.x = x

   @staticmethod
   def fun(str):
       return Name(str)

   @classmethod
   def fun1(cls,str):
       return cls(str)

print(Name.fun('str').x)

print(Name.fun1('str2').x)

4.7 数据封装和私有属性

python中相对于java而言没有private和protected这样的类别
因此我们在python中如何实现私有属性呢。
首先我们可以定义一个类

class User:
    def __init__(self, brithday):
        self.__brithday = brithday

    def get_age(self):
        return 2018-self.__brithday

这样我们在进行访问类创建的实例时,不能直接使用user.__brithday进行访问,否则会出现以下错误:

AttributeError: 'User' object has no attribute '__brithday'

但是可以在类的构造函数中进行访问,例如get_age()方法,可以直接进行访问;当然也可以直接让直接返回私有属性

    def get_brithday(self):
        return self.__brithday

python对于私有属性会进行一个变形,依旧可以进行私有属性进行访问

    print(user._User__brithday)

这样的方式,有一个优点,我们在进行A类继承B时,B的中的私有属性和A的私有属性分别会不同的类名前缀作为识别,从而避免重复的问题。

4.8 python对象的自省机制

python自省是通过一定的机制查询到内部的结构:

# 通过__dict__查询属性
class Person:
    name = 'user'

class Student(Person):
    def __init__(self, school_name):
        self.school_name = school_name

if __name__ == '__main__':
    user = Student('Liun')
    print(user.__dict__)
    print(Person.__dict__)
    print(user.name)

# 依次可以查询到如下信息
# {'school_name': 'Liun'}
#{'__module__': '__main__', 'name': 'user', '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
#user
# 如果你想要直接进行新的信息添加,可以使用以下方法
    user.__dict__['school_addr'] = '长沙'
    print(user.school_addr)
# dir可以列出对象的所有属性,相对于__dict__更加强大
	dir(user)

4.9 super函数

super调用父类函数

# 在进行父类的调用时,我们可以使用
class A:
    def __init__(self):
        print('A')

class B(A):
    def __init__(self):
        print('B')
        super().__init__()

if __name__ == '__main__':
    b = B()
# B
# A
# 其实super()在进行调用时并不是进行父类函数的直接调用,他是通过访问mro中的对象依次进行访问
class A:
    def __init__(self):
        print('A')

class B(A):
    def __init__(self):
        print('B')
        super().__init__()

class C(A):
    def __init__(self):
        print('C')
        super().__init__()

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

if __name__ == '__main__':
    print(D.__mro__)
    a = D()
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
# D B C A

4.10 python中多继承

mixin混合模式
1.Mixin功能单一
2.不和基类关联,可以和任何基类组合,基类可以不和Mixin关联就能初始化成功
3.在Mixin不要使用super函数

4.11 python的上下文管理器

python中的异常管理
try except finally

# 在try中的语句会被输出,然后由于没有捕获到keyError的错误,则会输出other err,并且finally始终会进行输出
try:
    print('code started')
    #raise IndexError
except KeyError as e:
    print('new code')
else:
    print('other err')
finally:
    print('finish')

# 未知行数的python读取
while True:
    try:
        s = input().strip()
        print(s)
    except EOFError as e:
        break
        
# python在进行上下文协议进行管理时,只要类的魔法函数中有enter和exit,我们就可以使用with语句进行上下文管理


先写到这,后面再补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值