gj4 深入类和对象
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_list def __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 NotImplementedError
def 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.abstractmethod
def get(self, key):
pass
@abc.abstractmethod
def 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 = y a = 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 = year
self.month = month
self.day = day def tomorrow(self):
self.day += 1
#静态方法
@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("-"))
return cls(int(year), int(month), int(day)) # 判断是否是合法的字符串,不需要反回函数
@staticmethod
def 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 True
else:
return False def __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-31
date_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.__birthyear if __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 = user
super().__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
A super() 调用的顺序是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: #没有抛异常才会运行 else
print ("other error")
finally: # 不管有没有异常,最后会执行
print ("finally") # 资源的释放 # ---
code started
key error
finally
# ---
def exe_try():
try:
print ("code started")
raise KeyError
return 1
except KeyError as e:
print ("key error")
return 2
else:
print ("other error")
return 3
finally:
print ("finally")
return 4 # 有返回值会反回,没有反回上一层的返回值
exe_try()
# ---
code started
key error
finally
4
# ---
# 上下文管理器协议, 由 __enter__,__exit__ 实现
# 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")
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 深入类和对象的更多相关文章
- Java编程里的类和对象
像我们搞计算机这块的,都知道这么一件事,当前的计算机编程语言主要分为两大块,一为面向过程,二为面向对象.Java就是一门纯面向对象的语言.学习了一个月左右的Java,在下对于Java当中的类和对象有了 ...
- Python - 类与对象的方法
类与对象的方法
- C++基础知识(5)---类和对象
终于把C++中的基础在前面的几篇博客中总结完了,可能还有一些语法还没有总结到,没关系,以后用到了再查资料就好.类是C++中的一个非常重要的概念,这是区别你使用的C++到底是面向过程还是面向对象的一个重 ...
- 简述JavaScript对象、数组对象与类数组对象
问题引出 在上图给出的文档中,用JavaScript获取那个a标签,要用什么办法呢?相信第一反应一定是使用document.getElementsByTagName('a')[0]来获取.同样的,在使 ...
- 前端学PHP之面向对象系列第一篇——类和对象
× 目录 [1]类 [2]成员属性[3]成员方法[4]对象[5]成员访问[6]this 前面的话 面向对象程序设计(OOP)是一种计算机编程架构.计算机程序由单个能够起到子程序作用的单元或对象组成,为 ...
- Objective-C Runtime 运行时之一:类与对象
Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理.这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一 ...
- [Java入门笔记] 面向对象编程基础(一):类和对象
什么是面向对象编程? 我们先来看看几个概念: 面向过程程序设计 面向过程,是根据事情发展的步骤,按进行的顺序过程划分,面向过程其实是最为实际的一种思考方式,可以说面向过程是一种基础的方法,它考虑的是实 ...
- 解析Java类和对象的初始化过程
类的初始化和对象初始化是 JVM 管理的类型生命周期中非常重要的两个环节,Google 了一遍网络,有关类装载机制的文章倒是不少,然而类初始化和对象初始化的文章并不多,特别是从字节码和 JVM 层次来 ...
- 02OC的类和对象
这章重点介绍OC的类以及对象,由于C语言是面向过程语言,而OC只是对于C语言多了一些面向对象的特性,所以OC相对于其他面向对象语言,例如C#.Java等没有那么多的语法特性,所以差别还是比较大的. 一 ...
随机推荐
- windows系统安装参数
winnt32 /dudisable /s:. /unattend:winnt.sif /makelocalsource /tempdrive:C /syspart:C 以上各参数解释如下: /dud ...
- 可视化库-seaborn-调色板(第五天)
1. 基础的调色板的演示 color_palette() 设置传入的任何颜色,不传使用默认颜色,set_palette() 设置所有图的颜色# 6种主题 # 1 deep# 2 muted# 3 p ...
- 基于OpenGL编写一个简易的2D渲染框架-06 编写一个粒子系统
在这篇文章中,我将详细说明如何编写一个简易的粒子系统. 粒子系统可以模拟许多效果,下图便是这次的粒子系统的显示效果.为了方便演示,就弄成了一个动图. 图中,同时显示了 7 种不同粒子效果,看上去效果挺 ...
- pycharm专业版(window)安装
1.官网下载 2. 3.直接finlsh 4. 5. https://pan.baidu.com/s/1mQcc98iJS5bnIyrC6097yA 密码:b1c1
- 切换svn登录账户
右键-->TortoiseSVN-->设置 找到:点击已缓存数据 在认证数据一栏点击:清空
- 在JSP页面中显示动态时间
源地址:http://blog.csdn.net/aitcax/article/details/41285305 静态时间: 1.页面首部添加 <%@page import="java ...
- VirtualBox如何扩展虚拟机Ubuntu的硬盘容量?
一.问题描述 刚刚在VirtualBox中使用Ubuntu虚拟机中,出现了虚拟硬盘不够用的情况. 乖乖,查了一下磁盘空间,如下所示: df -H 原来是上午安装Ubuntu虚拟机的时候,选择了动态分 ...
- linux 下 安装nginx及压力测试
linux 编译安装nginx,配置自启动脚本 下载nginx: wget http://nginx.org/download/nginx-1.8.0.tar.gz下载openssl : wget h ...
- 常用数据库ID格式
转自:http://www.biotrainee.com/thread-411-1-1.html 常用数据库 ID ID 示例 ID 来源 ENSG00000116717 Ensemble ID GA ...
- 第八章 高级搜索树 (b1)B-树:动机