python深入理解类和对象
1,鸭子类型和多态
当看到一只鸟走起来像鸭子,游泳起来像鸭子,叫起来也像鸭子,那这只鸟就是鸭子
是不是比较混乱,看个例子:
# -*- coding:UTF-8 -*-
__autor__ = 'zhouli'
__date__ = '2018/11/14 20:46' class Cat:
def say(self):
print('iam a cat') class Dog:
def say(self):
print('iam a dog') class Duck:
def say(self):
print('iam a duck') animal_list = [Cat, Dog, Duck]
for animal in animal_list:
animal().say()
结果如下:
iam a cat
iam a dog
iam a duck
在这个地方三个类实现了同一个方法,这样就是一种多态,什么叫鸭子类型呢,就是所有类都实现共同的方法,所有的方法名称都一样,这样就是鸭子类型
2,类的三个方法:
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)) @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 @classmethod
def from_string(cls, date_str):
year, month, day = tuple(date_str.split("-"))
return cls(int(year), int(month), int(day)) 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-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"))
所谓静态方法就相当于将需要外部调用的方法集成到类的内部,将命名空间并入到类中
类方法相比静态方法,不在需要硬编码了
实例方法就很简单了,使用实例+方法+()即可
3,super函数:
先看一个简单的例子:
# -*- coding:UTF-8 -*-
__autor__ = 'zhouli'
__date__ = '2018/11/17 21:18' class A:
def __init__(self):
print('A') class B(A):
def __init__(self):
print('B')
# super(B, self).__init__() # python2的用法
super().__init__() # 既然已经重写了B的构造函数,为什么还要去调用super
# super到底执行顺序是什么
if __name__ == '__main__':
b = B()
打印结果如下:但是我们得思考2个问题,①既然已经重写了B的构造函数,为什么还要去调用super
② super到底执行顺序是什么
# -*- coding:UTF-8 -*-
__autor__ = 'zhouli'
__date__ = '2018/11/17 21:18' class A:
def __init__(self,user,name):
print('A')
self.user = user
self.name = name class B(A):
def __init__(self,user,name):
self.user = user
print('B')
super().__init__(name=name) if __name__ == '__main__':
b = B()
可以看到B类中继承A类中,如果定义父类中的部分方法,所以为了节省代码,因此采用super
super函数并不是简单的调用父类的方法,先看代码
# -*- coding:UTF-8 -*-
__autor__ = 'zhouli'
__date__ = '2018/11/17 21:18' 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__':
D = D()
D回去调用父类的函数,因为B在C之前,所以会有限调用
结果如下:但是注意到B在调用super之后打印的是C,而不是A
如果super是简单调用父类的构造函数的话,那么久不成立了
为什么会打印出这样的结果呢?
因为super是执行D的__mro__
print(D.__mro__)
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
这两个数据顺序是保持一致的!
4,Mixin继承混合模式(除非万不得已,不要使用多继承)
Mixin其实和普通的多继承是本质一样的,但是Mixin有两个特点:
① Minin里面功能比较单一,尽量简化
② 不和我们真正的类一样,不和基类关联,可以和任意基类组合,基类不和Mixin关联就能初始化成功,Minin只是定义了一个方法
③ Minin中不要使用super的方法,因为super会根据mro算法去调用他的方法,因为尽量不要和基类关联
④ 命名尽量使用Mixin结尾(约定俗成)
class GoodsListViewSet(CacheResponseMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
"""
商品列表页, 分页, 搜索, 过滤, 排序
"""
# throttle_classes = (UserRateThrottle, )
queryset = Goods.objects.all()
serializer_class = GoodsSerializer
pagination_class = GoodsPagination
# authentication_classes = (TokenAuthentication, )
filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
filter_class = GoodsFilter
search_fields = ('name', 'goods_brief', 'goods_desc')
ordering_fields = ('sold_num', 'shop_price') def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
instance.click_num += 1
instance.save()
serializer = self.get_serializer(instance)
return Response(serializer.data)
在这个类中,一个类可以完成商品列表页, 分页, 搜索, 过滤, 排序,
class ListModelMixin(object):
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
5,上下文管理器:
#上下文管理器协议
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()
上下文如果使用with语句就必须在类中定义这个两个方法
那如何简化这个上下文管理器呢?
import contextlib @contextlib.contextmanager
def file_open(file_name):
print("file open")
yield {}
print("file end") with file_open("bobby.txt") as f_opened:
print("file processing")
在python中提供了一个contextlib模块
在上面的__enter__中的所有代码全部在yield之前操作
在yield之后是原来的__exit__方法全部放在里面
当然函数的上方必须要加上装饰器@contextlib.contextmanager
6,使用bisect
import bisect
from collections import deque #用来处理已排序的序列,用来维持已排序的序列, 升序
#二分查找
inter_list = deque()
bisect.insort(inter_list, 3)
bisect.insort(inter_list, 2)
bisect.insort(inter_list, 5)
bisect.insort(inter_list, 1)
bisect.insort(inter_list, 6) print(bisect.bisect_left(inter_list, 3))
#学习成绩
print(inter_list)
结果如下:
2
deque([1, 2, 3, 5, 6])
但是如果一旦插入一个相同的数字,左插入和右插入又有何分别呢?
其实在一定的时候,比方说3和3.0相比或者是对成绩的排序时候有讲究
python深入理解类和对象的更多相关文章
- 初识python中的类与对象
这篇博客的路线是由深入浅,所以尽管图画的花花绿绿的很好看,但是请先关注我的文字,因为初接触类的小伙伴直接看类的实现可能会觉得难度大,只要耐着性子看下去,就会有一种“拨开迷雾看未来”的感觉了. 一.py ...
- python入门17 类和对象
类:一类事物的抽象化.概念: 类的变量(属于类的变量,定义在类的开始处) 成员变量(self.变量) 类的方法( @classmethod,cls参数) 成员方法( self参数 ) 静态方法 ...
- Python之面向对象类和对象
Python之面向对象类和对象 定义一个类:class 定义类的语法: class Test(object): """ 类里定义一类事物共同的技能. 可以是变量,也可是函 ...
- 理解类、对象、实例、原型链以及继承 - WPF特工队内部资料
理解类.对象.实例.原型链以及继承 <!DOCTYPE html> <html lang="en"> <head> <meta chars ...
- 非常易于理解‘类'与'对象’ 间 属性 引用关系,暨《Python 中的引用和类属性的初步理解》读后感
关键字:名称,名称空间,引用,指针,指针类型的指针(即指向指针的指针) 我读完后的理解总结: 1. 我们知道,python中的变量的赋值操作,变量其实就是一个名称name,赋值就是将name引用到一个 ...
- python中的类,对象,方法,属性等介绍
注:这篇文章写得很好.加底纹的是我自己的理解 python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象...... 我们通过描述属性( ...
- Python 面向对象(创建类和对象,面向对象的三大特性是指:封装、继承和多态,多态性)
概念: ...
- Python里的类和对象简介
---恢复内容开始--- Python里的类 对象=属性+方法: 对象的属性主要是指主要的特征和参量,而方法主要是指函数: 类是一个具有一定特征和方法的集合,而对象是类的一个:类和对象的关系就如同模 ...
- Python进阶-XV 类和对象的命名空间 组合
一.类和对象命名空间 1.类中可以定义两种属性 静态属性和动态属性 class Course: language = 'Chinese' # 静态属性 def __init__(self, name, ...
随机推荐
- Python3之set, frozenset记录
set1 = set([1, 2, 3, 4]) set2 = frozenset([1, 2, 3, 4]) print(set1, set2, sep='|||') set1.add(" ...
- JDK8安装与配置
如果是免安装包 配置方法 1.配置java环境变量 注意:jdk文件夹名字取名不要用汉语取名. 1)鼠标右键点击我的电脑(计算机)选择属性栏 2)再点击左边高级系统设置 3)点击环境变量 4)在系统变 ...
- 在 delphiXE 10.2 上安装 FR5.4.6
今天在虚拟机里成功安装了delphiXE 10.2, 然后想把常用的FR也装上,本想偷个懒,在网上找个装上就得了,结果发现必须要在发布的网站注册才能下载⊙︿⊙ 如此麻烦,心里这个不爽啊不爽! 然后自己 ...
- [转]Windows下使用VS2015编译openssl库
转自:http://blog.csdn.net/alger_magic/article/details/52584171 目标:编译vs环境下openssl库 工具: 1. 编译环境win10+vs2 ...
- PostgreSQL获取所有表名、字段名、字段类型、注释
转载自:http://blog.csdn.net/cicon/article/details/51577655 获取表名及注释: select relname as tabname,cast(obj_ ...
- linux下C语言多线程编程实例
用一个实例.来学习linux下C语言多线程编程实例. 代码目的:通过创建两个线程来实现对一个数的递加.代码: //包含的头文件 #include <pthread.h> #include ...
- 解决配置Windows Update失败,还原更改问题
问题描述 由于配置Windows Update失败,还原更改状态下无法正常关机.只能长按电源键关机后进入WinPE环境. 解决步骤 进入WinPE环境->选择Dism++->选择版本-&g ...
- MySQL学习笔记Windows篇<一> Welcome to MySQL
MySQL安装完毕后没有图形化操作界面,图形化管理界面需要另行安装,个人比较喜欢Navicat,界面更像SQLserver: 此篇学习笔记所有操作均使用命令行中完成: 1.开启/停止服务 使用MySQ ...
- 203. 阿里jetcache
[视频&交流平台] àSpringBoot视频:http://t.cn/R3QepWG à SpringCloud视频:http://t.cn/R3QeRZc à Spring Boot源码: ...
- Android开发中常见的设计模式(四)——策略模式
策略模式定义了一些列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变换. 假设我们要出去旅游,而去旅游出行的方式有很多,有步行,有坐火车,有坐飞机等等 ...