4.1 鸭子类型和多态

当看到一只鸟走起来像鸭子、游永起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子

只要利用Python的魔法函数,就能实现某些Python数据类型的类似的方法。

class Cat(object):def say(self):print("i am a cat")class Dog(object):def say(self):print("i am a fish")
class Duck(object):def say(self):print("i am a duck")animal_list=[Cat,Dog,Duck]
for animal in animal_list:animal().say()# 不同的对象实现了相同的方法,多态i am a cat
i am a fish
i am a duck
---a = ["lewen1", "lewen2"]
b = ["lewen2", "lewen"]
name_tuple = ["lewen3", "lewen4"]
name_set = set()
name_set.add("lewen5")
name_set.add("lewen6")
a.extend(name_set) # extend() 括号里面为可迭代对象
print(a)['lewen1', 'lewen2', 'lewen6', 'lewen5']
---class Company(object):def __init__(self, employee_list):self.employee = employee_listdef __getitem__(self, item):return self.employee[item]def __len__(self):return len(self.employee)company = Company(["tom", "bob", "jane"])
b.extend(company) # 可以接受
print(b)['lewen2', 'lewen', 'tom', 'bob', 'jane']

4.2 抽象基类(abc模块)

Python的变量不需指定类型,可以动态修改类型(多态)
不同的魔法函数赋予了不同的特性
不需要继承某个类,只需要实现相应的魔法函数就可以实现特定的方法
抽象基类无法被实例化
#我们去检查某个类是否有某种方法
class Company(object):def __init__(self, employee_list):self.employee = employee_list
​def __len__(self):return len(self.employee)
​
​
com = Company(["bobby1","bobby2"])
print(hasattr(com, "__len__"))
True
#我们在某些情况之下希望判定某个对象是否是某个类型
from collections.abc import Sized
isinstance(com, Sized)
class A:pass
​
class B(A):pass
​
b = B()
print(isinstance(b, A))
True
#我们需要强制某个子类必须实现某些方法
#实现了一个web框架,集成cache(redis, cache, memorychache)
#需要设计一个抽象基类, 指定子类必须实现某些方法
​
#如何去模拟一个抽象基类
​
class CacheBase(object):def get(self, key):raise NotImplementedErrordef set(self, key, value):raise NotImplementedError
​
# class RedisCache(CacheBase):
#     pass                           #没有实现父类对应的方法,调用时会报错
class RedisCache(CacheBase):def set(self, key, value):      #调用不会再报错pass
​
redis_cache = RedisCache()
redis_cache.set("key", "value")
#上面更规范的写法
import abc
#from collections.abc import *
​
​
class CacheBase(metaclass=abc.ABCMeta):@abc.abstractmethoddef get(self, key):pass
​@abc.abstractmethoddef set(self, key, value):pass
class RedisCache(CacheBase):
#     def set(self, key, value):pass
redis_cache = RedisCache()    #初始化的时候就需要重载基类被装饰器修饰的方法
# redis_cache.set("key", "value")
---------------------------------------------------------------------------
​
TypeError                                 Traceback (most recent call last)
​
<ipython-input-16-a30c00982960> in <module>15 #     def set(self, key, value):16         pass
---> 17 redis_cache = RedisCache()    #初始化的时候就需要重载基类方法18 # redis_cache.set("key", "value")
TypeError: Can't instantiate abstract class RedisCache with abstract methods get, set
抽象基类用的比较少
​
mixin

e

4.3 使用isintance而不是type

class A:pass
​
class B(A):pass
​
b = B()
​
print(isinstance(b, B))
print(isinstance(b, A))
​
print(type(b))
print(type(b) is B)  #  is 去判断两个对象是不是一个对象,
print(type(b) == B)  # == 是对值是否相等的判断
print(type(b) is A)
print(isinstance(b, A))
True
True
<class '__main__.B'>
True
True
False
True
尽量使用isinstance 而不是type去判断一个类型isinstance 返回一个对象是否是类或其子类的一个实例。(Return whether an object is an instance of a class or of a subclass thereof)type 对象的类型

4.4 类变量和对象变量

class A:aa = 1 # 类变量def __init__(self, x, y):self.x = x        # 实例变量self.y = ya = A(2,3)A.aa = 11     # 修改类变量
a.aa = 100    # 将值赋给实例变量
print(a.x, a.y, a.aa)print(A.aa)b = A(3,5)
print(b.aa)
---
2 3 100
11
11

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

深度优先

这种深度优先就不再合理,如果C重载了D的方法,而找了B直接找D,C就没有用了

再Python3以后修改了这种搜索,为广度优先

C和D有重名的话,理应找完B再找D,而广度优先就会使C覆盖掉D

Python3 都是采用的深度优先

#C3算法

小结:py3 有共同父类(菱形)的广度优先,没有共同父类的深度优先

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

class Date:#构造函数def __init__(self, year, month, day):self.year = yearself.month = monthself.day = daydef tomorrow(self):self.day += 1#静态方法    @staticmethoddef parse_from_string(date_str):year, month, day = tuple(date_str.split("-"))return Date(int(year), int(month), int(day))#硬编码的方式,只要类名修改,这反回的类名就得修改#类方法@classmethoddef from_string(cls, date_str):year, month, day = tuple(date_str.split("-"))return cls(int(year), int(month), int(day))# 判断是否是合法的字符串,不需要反回函数@staticmethoddef valid_str(date_str):year, month, day = tuple(date_str.split("-"))if int(year)>0 and (int(month) >0 and int(month)<=12) and (int(day) >0 and int(day)<=31):return Trueelse:return Falsedef __str__(self):return "{year}/{month}/{day}".format(year=self.year, month=self.month, day=self.day)
​
if __name__ == "__main__":new_day = Date(2018, 12, 31)new_day.tomorrow()print(new_day)
2018/12/32#2018-12-31date_str = "2018-12-31"year, month, day = tuple(date_str.split("-"))new_day = Date(int(year), int(month), int(day))print (new_day)#用staticmethod(静态方法)完成初始化new_day = Date.parse_from_string(date_str)print (new_day)#用classmethod完成初始化new_day = Date.from_string(date_str)print(new_day)
​print(Date.valid_str("2018-12-32"))
2018/12/31
2018/12/31
2018/12/31
False
​
​

4.7 数据封装和私有属性

class User:def __init__(self, birthyear):self.__birthyear = birthyear  # 双下划线def get_age(self):# 返回年龄return 2018 - self.__birthyearif __name__ == "__main__":user = User(1990)print(user.get_age())# print(user.__birthyear)  # 私有属性是无法通过,实例访问的print(user._User__birthyear)  # 双下划线并不是绝对安全的
"""
28
1990
"""

4.8 python对象的自省机制

#自省是通过一定的机制查询到对象的内部结构
​
class Person:name = "user"
​
class Student(Person):def __init__(self, scool_name):self.scool_name = scool_name
​
​
user = Student("慕课网")
#通过__dict__查询属性
print(user.__dict__)

#---
{'scool_name': '慕课网'}
#---
user.__dict__["school_addr"] = "北京市"
print(user.school_addr)
#---
北京市
#---
print(Person.__dict__)
print(user.name)
#---
{'__module__': '__main__', 'name': 'user', '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
user
#---
a = [1,2]
print(dir(a))
#---
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

4.9 super函数

class A:def __init__(self):print ("A")
​
class B(A):def __init__(self):print ("B")#super(B,self).__init__()  # py2中的写法super().__init__()
​
b = B()
#---
B
A
既然我们重写B的构造函数, 为什么还要去调用super?
super到底执行顺序是什么样的?from threading import Thread
class MyThread(Thread):def __init__(self, name, user):self.user = usersuper().__init__(name=name)  # 重用父类的代码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(D, self).__init__()
​
if __name__ == "__main__":print(D.__mro__)d = D()
​
# 有共同父类,广度优先
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
D
B
C
Asuper() 调用的顺序是mro的顺序

4.10 django rest framework中对多继承使用的经验

mixin(混合继承)模式特点
1. Mixin类功能单一(一个mixin实现一个功能)
2. 不和基类关联,可以和任意基类组合。 基类可以不和mixin关联就能初始化成功
3. 在mixin中不要使用super这种用法

django中一个类继承多个mixin类实现多个功能

  

4.11 python中的with语句

try:print ("code started")raise KeyError
except KeyError as e:print ("key error")
else:                           #没有抛异常才会运行 elseprint ("other error")
finally:                        # 不管有没有异常,最后会执行print ("finally")           # 资源的释放# ---
code started
key error
finally
# ---
def exe_try():try:print ("code started")raise KeyErrorreturn 1except KeyError as e:print ("key error")return 2else:print ("other error")return 3finally:print ("finally")return 4  # 有返回值会反回,没有反回上一层的返回值
exe_try()
# ---
code started
key error
finally
4
# ---
# 上下文管理器协议, 由 __enter__,__exit__ 实现
# with 支持上下文管理器协议
class Sample:def __enter__(self):print ("enter")#获取资源return selfdef __exit__(self, exc_type, exc_val, exc_tb):#释放资源print ("exit")def do_something(self):print ("doing something")
​
with Sample() as sample:sample.do_something()# ---
enter
doing something
exit
​

4.12 contextlib实现上下文管理器

import contextlib          #上下文管理器
@contextlib.contextmanager  # 用装饰器,将一个函数变成上下文管理器
def file_open(file_name):print ("file open")yield {}   # 必须是生成器print ("file end")with file_open("lewen.txt") as f_opened:print ("file processing")---
file open
file processing
file end
---

Python 本身没有接口,利用魔法函数的组合,和协议实现某些数据类型的属性

gj4 深入类和对象相关推荐

  1. C++ 笔记(18)— 类和对象(this 指针、指向类的指针、类静态成员变量和函数)

    1. this 指针 在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址. this 指针是所有成员函数的隐含参数.因此,在成员函数内部,它可以用来指向调用对象. 友元函数没有 thi ...

  2. C++ 笔记(16)— 类和对象(类定义、类实例对象定义、访问类成员、类成员函数、类 public/private/protected 成员、类对象引用和指针)

    1. 类的定义 类定义是以关键字 class 开头,后跟类的名称.并在它后面依次包含类名,一组放在 {} 内的成员属性和成员函数,以及结尾的分号. 类声明将类本身及其属性告诉编译器.类声明本身并不能改 ...

  3. C02-程序设计基础提高班(C++)第9周上机任务-类和对象

    第9周:阅读教材第8章(p231-262),主要内容是类和对象,学会定义类和对象解决问题,完成第9周上机任务: (回到C02-程序设计基础提高班(C++)学习安排) 实践任务: [任务1]阅读.运行下 ...

  4. 函数返回类的对象与拷贝构造函数

    C++中,如果我们在一个函数中,定义了一个类的对象,然后返回这个对象,在main函数中用一个对象去接受这个返回的对象的时候,这里面参与的函数调用大家可能不熟悉,这里通过程序和注释的方式给大家讲解一下. ...

  5. ZJU-java进阶笔记 第一、二周(类与对象,对象交互)

    对象变量是对象的管理者,而非所有者 VendingMachine vm = new VendingMachine(); this指代当前对象 成员函数可以直接(不需要点运算符)调用本类的其他成员函数 ...

  6. 3个题目熟悉类和对象基础

    1.按要求编写Java应用程序: (1)编写西游记人物类(XiYouJiRenWu)其中属性有:身高(height),名字(name),武器(weapon)方法有:显示名字(printName),显示 ...

  7. 刻意练习:Python基础 -- Task10. 类与对象

    背景 我们准备利用17天时间,将 "Python基础的刻意练习" 分为如下任务: Task01:变量.运算符与数据类型(1day) Task02:条件与循环(1day) Task0 ...

  8. java中具有继承关系的类及其对象初始化顺序

    先说结论 对于具有继承关系的类,它们的类和对象构造顺序为:父类的类构造器() -> 子类的类构造器() -> 父类成员变量的赋值和实例代码块 -> 父类的构造函数 -> 子类成 ...

  9. python的类和对象_Python类与对象实验

    一.任务描述 本实验任务主要对Python类与对象进行一些基本操作,通过完成本实验任务,要求学生熟练掌握Python类与对象的关系,并对Python类与对象的基本操作进行整理并填写工作任务报告. 二. ...

最新文章

  1. Session分布式共享 = Session + Redis + Nginx
  2. pytorch 激活函数
  3. 十五、linux 注册字符类设备和生成节点
  4. java有参数 无参数方法
  5. 记一次 .NET 某WMS仓储打单系统 内存暴涨分析
  6. linux任务处理函数,Linux信号掩码和信号处理函数
  7. mac 遇到的奇怪问题?
  8. A-Night at the Museum 水题
  9. Stm32CubeMx lwip+freeRTOS TCP 服务
  10. DevExpress v18.1新版亮点——WPF篇(二)
  11. 2019 Web 前端热点笔试面试题总结(转载)
  12. LTE下行物理层传输机制(9)-集中式和分布式资源映射
  13. l7sa008b故障代码_Robertshaw 365-A8振动开关故障探测器
  14. 动作电位的产生和动作电位的长距离高速传导
  15. 一定要学会了解大数据
  16. Android 图片裁切框架 uCrop 的用法
  17. python导入数学函数_Python 数学函数模块(Math)
  18. react-native打包失败: Expiring daemon because jvm heap space is exhausted
  19. TesterHome android app 编写历程(六)
  20. 线性代数拾遗(1)—— 行列式的三种公理化构造

热门文章

  1. java 面试问jdk版本_面试常被问到的 JDK 命令,你知道几个?
  2. 编写一个弹出式菜单的shell程序_分享一个有趣的shell脚本--实现抓阄程序
  3. hpux oracle9,oracle 9i,10G,11G,各版本下载资源
  4. power系列服务器问题品管主任,了解 Power BI 管理员角色
  5. php环境搭建5.6_WIN8.1下搭建PHP5.6环境
  6. 卸载源码安装mysql_CentOS 7.x 卸载删除MariaDB,重新安装,安装MYSQL离线版和源代码...
  7. springboot通过Intellij指定端口
  8. 分享珍藏很久的Python学习知识手册
  9. 2019,GMIS归来!杨强、吴恩达等全球重磅嘉宾共话数据智能
  10. 关于进程与线程,史上最浅显易懂的一个简单解释!