2.python深入类和对象

1.1.鸭子类型和多态

实现了__getitem__方法

class Company(object):
    def __init__(self, employee_list):
        self.employee = employee_list

    def __getitem__(self, item):
        return self.employee[item]

company = Company(["11", "22", "33"])
a = ['derek1','derek2']

name_set = set()
name_set.add('tom1')
name_set.add(('tom2'))

#extend里面可以添加任何可迭代的参数,
#给类添加一个魔法函数__getitem__,类就变成可迭代的
a.extend(company)
print(a) #['derek1', 'derek2', '11', '22', '33']

a.extend(name_set)
print(a) #['derek1', 'derek2', '11', '22', '33', 'tom2', 'tom1']

1.2.抽象基类(abc模块)待完善

抽象基类的作用类似于JAVA中的接口。在接口中定义各种方法,然后继承接口的各种类进行具体方法的实现。抽象基类就是定义各种方法而不做具体实现的类,任何继承自抽象基类的类必须实现这些方法,否则无法实例化

(1)判断类时候有某种属性

#判断类是否有某种属性
class Company(object):
    def __init__(self, employee_list):
        self.employee = employee_list

    def __len__(self):
        return len(self.employee)

com = Company(["11", "22", "33"])
#hasattr判断类有没有某种属性,方法也是类的属性
print(hasattr(com,"__len__"))   #True

#虽然用hasattr可以判断,但正确的方式是定义一个抽象基类
#判定某个对象的类型,可以用抽象基类
from collections import Sized
print(isinstance(com,Sized)) #True 注释掉def __len__返回false

1.3.使用isinstance而不是type

类型即 (tuple,dict,int,float,list,bool等)

>>> isinstance(1,int)
True
>>> 
>>> isinstance('1',str)
True
>>> 
>>> isinstance(1,list)
False

(3)type()与isinstance()的区别:

  • 共同点都可以判断对象类型
  • 不同点对于一个 class 类的子类对象类型判断,type就不行了,而 isinstance 可以。
class A:
    pass

class B(A):
    pass

b = B()

#判断b是不是B的类型
print(isinstance(b,B))        #True
#isinstance内部会去检查继承链
print(isinstance(b,A))        #True

print(type(b) is B)           #True
#b指向了B()对象,虽然A是B的父类,但是A是另外一个对象,它们的id是不相等的
print(type(b) is A)           #False

1.4.类变量和实例变量

class A:
    #类变量
    bb = 11
    def __init__(self,x,y):
        #实例变量
        self.x = x
        self.y = y

a = A(2,3)
A.bb = 111111
print(a.x,a.y,a.bb)    # 2 3 111111
print(A.bb)            # 111111

a.bb = 2222     #实际上会在实例对象a里面新建一个属性bb
print(a.bb)          # 2222
print(A.bb)          # 111111

1.5.类和实例属性的查找顺序

class D(object):
    pass

class C(D):
    pass

class B(D):
    pass

class A(B,C):
    pass

#顺序:A,B,C,D
#__mro__,类的属性查找顺序(「方法解析顺序」(Method Resolution Order)
print(A.__mro__)
#(<class '__main__.A'>, <class '__main__.B'>,
# <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)

 

class D(object):
    pass

class E(object):
    pass

class C(E):
    pass

class B(D):
    pass

class A(B,C):
    pass

#顺序:A,B,D,C,E
print(A.__mro__)

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

class Date():
    #构造函数
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day

    #实例方法
    def tomorrow(self):
        self.day += 1

    # 静态方法不用写self
    @staticmethod
    def parse_from_string(date_str):
        year, month, day = tuple(date_str.split("-"))
        # 静态方法不好的地方是采用硬编码,如果用类方法的话就不会了
        return Date(int(year), int(month), int(day))

    #类方法
    @classmethod
    def from_string(cls, date_str):
        year, month, day = tuple(date_str.split("-"))
        # cls:传进来的类,而不是像静态方法把类写死了
        return cls(int(year), int(month), int(day))

    def __str__(self):
        return '%s/%s/%s'%(self.year,self.month,self.day)

if __name__ == "__main__":
    new_day = Date(2018,5,9)
    #实例方法
    new_day.tomorrow()
    print(new_day)       #2018/5/10

    #静态方法
    date_str = '2018-05-09'
    new_day = Date.parse_from_string(date_str)
    print(new_day)       #2018/5/9

    # 类方法
    date_str = '2018-05-09'
    new_day = Date.from_string(date_str)
    print(new_day)  # 2018/5/9

1.7.python对象的自省机制

class Person:
    '''人类'''
    name = "user"

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

if __name__ == "__main__":

    user = Student('仙剑')
    #通过 __dict__ 查询有哪些属性
    print(user.__dict__)        #{'school_name': '仙剑'}

    print(Person.__dict__)  #{'__module__': '__main__', '__doc__': '人类', 'name': 'user', 
'__dict__': <attribute '__dict__' of 'Person' objects>, 
'__weakref__': <attribute '__weakref__' of 'Person' objects>}

    print(Person.__doc__)       #人类

    #可以添加属性
    user.__dict__['school_addr'] = '北京'
    print(user.school_addr)     #北京

    #dir也可以查看属性,比__dict__功能更强大
    print(dir(user))
#['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', 
'__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', 
'__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 
'name', 'school_addr', 'school_name']

1.8.super函数

super执行的顺序

class A(object):
    def __init__(self):
        print('A')

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

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

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

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

1.9.with语句(上下文管理器)

#上下文管理器
class Sample:
    def __enter__(self):
        print('enter')
        #获取资源
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        #释放资源
        print('exit')

    def do_something(self):
        print('doing something')

#会自动执行enter和exit方法
with Sample() as sample:
    sample.do_something()

# 运行结果
enter
doing something
exit

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值