中企动力 > 头条 > python子类

网站性能检测评分

注:本网站页面html检测工具扫描网站中存在的基本问题,仅供参考。

python子类

Python多线程的基本套路你知道么? 互联网视频课程

img

妙柏

关注

概述

python对多线程的支持

先看一个概念:

官方描述:In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

由于GIL的存在,python其实无法利用多处理器的优势,任意时刻只会有一个线程运行在解释器中,也就是大计算量的程序在python中通过多线程处理其实不见得会变快。但是IO密集型程序可以很好地利用多线程,比如用python开发一个rest客户端程序,如果单线程实现,假如发送一个http请求服务器端需要耗费5s来处理,串行发送1000个就需要5000s左右;但是开1000个线程,就可以同时发送1000个请求,一起等待相应,基本10s之内就能完成这个过程。

Python中多线程相关的模块包括:thread,threading,Queue。

thread:多线程的底层支持模块,一般不建议使用【本文暂不涉及】

threading:对thread进行了封装,将一些线程的操作对象化

Queue:实现了多生产者(Producer)、多消费者(Consumer)的队列

喜欢的话关注收藏评论转发比心么么哒!Python学习交流群330637182内有大量的项目开发和新手教学视频五千人大群等着你来加入

开始使用多线程

入门例子

python的threading库可以实现在单独的线程中执行任意的python可调用对象,我们通过创建Thread类的实例,然后提供其需要被单独线程执行的可调用对象,就完成目的了,看一个入门例子:

创建一个线程实例需要传递给它目标函数的引用,参数元组,然后调用start方法就会开始这个线程的运行。

通过Thread类可以有多种方法创建线程:

用一个函数作为参数实例化一个Thread类,多线程执行这个函数(上面例子所示)

用一个可调用类作为参数实例化一个Thread类,多线程执行这个“可调用类”(和第一个本质相同)

从Thread类派生一个子类,重写run方法(比较常规的用法)

多线程中的join

观察上面输出会发现“All done!”居然在最开始输出了,我们的本意是线程执行完之后才输出“All done!”,咋办呢?看下面一段代码:

这里介绍一下这个join,文档中有如下一句话:

"Wait until the thread terminates"

也就是说要等待这个线程执行完毕才开始后续操作,这样就实现了等待子线程完成再进行其他操作的目的。

该函数定义是def join(self, timeout=None): ...

也就是说还可以设置timeout参数,避免子线程出问题一直不结束的情况下父线程无限等待的问题

用一个可调用类作为参数实例化一个Thread类

先看下面代码:

如上,其实这里很好理解,主要注意的一个知识点是类的“call()”方法,这里的target is a callable object, 是一个可调用对象,MyThread(show, ('wing',))实例化了一个类,得到的对象就是这样一个可调用对象,和函数名对应,真正调用的时候就是执行了__call__()方法,这里的__call__()只是简单地执行初始化时传递过来的函数,类来实现相比于函数要灵活很多。

从Thread类派生一个子类,重写run方法(推荐的方法)

代码:

这里继承了threading模块的Thread类,重写了init和run方法,通过这种方式来实现多线程执行的效果。

多线程处理的返回值问题

上面的show函数只是简单的打印操作,但是如果需要多线程处理的函数如下:

这个时候需要记录函数执行的结果,在上面的实现中并不能达到这样的效果,这个时候我们可以稍微修改一下MyThread类,如下:

python线程同步机制

最后的结果是0,准确说多次执行发现结果是0,至于0是不是唯一结果,这里先不下结论,如果我们尝试把sleep(1)这一句注释放开,就会发现结果基本变成了-1

其实这里的sleep表示的只是对count操作之前的过程可能会耗时较长,这个时候count可能已经被改变了,而我们的本意是count大于0时才执行一次操作,本线程做这个处理的时候,不希望其他线程同时操作count的值。

再看下面一段代码:

如上,通过加锁实现了线程同步,这里的锁释放还可以用更优雅的方式实现,如下:

python面向对象三大特性之多态 公司视频课程

img

小费

关注

多态

目标

多态

面向对象三大特性

1. 封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中

定义类的准则

2. 继承 实现代码的重用,相同的代码不需要重复的编写

设计类的技巧

子类针对自己特有的需求,编写特定的代码

3. 多态 不同的 子类对象 调用相同的 父类方法,产生不同的执行结果

多态 可以 增加代码的灵活度

以 继承 和 重写父类方法 为前提

是调用方法的技巧,不会影响到类的内部设计

多态案例演练

需求

1. 在 `Dog` 类中封装方法 `game`

普通狗只是简单的玩耍

2. 定义 `XiaoTianDog` 继承自 `Dog`,并且重写 `game` 方法

哮天犬需要在天上玩耍

3. 定义 `Person` 类,并且封装一个 和狗玩 的方法

在方法内部,直接让 狗对象 调用 `game` 方法

案例小结

`Person` 类中只需要让 狗对象 调用 `game` 方法,而不关心具体是 什么狗

`game` 方法是在 `Dog` 父类中定义的

在程序执行时,传入不同的 狗对象 实参,就会产生不同的执行效果

> 多态 更容易编写出出通用的代码,做出通用的编程,以适应需求的不断变化

```python

class Dog(object):

def __init__(self, name):

self.name = name

def game(self):

print("%s 蹦蹦跳跳的玩耍..." % self.name)

class XiaoTianDog(Dog):

def game(self):

print("%s 飞到天上去玩耍..." % self.name)

class Person(object):

def __init__(self, name):

self.name = name

def game_with_dog(self, dog):

print("%s 和 %s 快乐的玩耍..." % (self.name, dog.name))

让狗玩耍

dog.game()

1. 创建一个狗对象

wangcai = Dog("旺财")

wangcai = XiaoTianDog("飞天旺财")

2. 创建一个小明对象

xiaoming = Person("小明")

3. 让小明调用和狗玩的方法

xiaoming.game_with_dog(wangcai)

面向对象特性之二:继承(Python进阶教程) 推广视频课程

img

布兰登

关注

上一篇文章介绍了面向对象特性之——封装(参考之前发文《面向对象特性之一:封装(Python进阶教程)》),想必大家对面向对象的这种编程思想应该有了一定的了解。今天我们再来研究一下面向对象的第二种特性——继承;

“继承”从字面意思上很好理解,儿子和爸爸长的很像,性格也类似,一看就知道是亲生的。但是呢,又不完全一样,儿子拥有他自己的特征。在程序上面,“继承”这种思想也类似于平时我们所理解的概念。下面,让我们接着以“快递公司老板”这个例子来说明“继承”在Python中的用法和优点;

你开的快递公司生意已经很好了,不得不再增加一个部门,这个部门是从属于之前的“员工”部门的一个子部门,专门负责给国外的客户收发快递,那么,这个子部门类可以继承之前的“员工”部门类,从而增加一个继承的子类,这个子类具有和其父类相同的属性、方法,也可根据逻辑单独在子类里定义其他方法,这样的类与类的关系就叫做继承关系,我们看一下代码:

父类“员工类”

这是之前创建的一个员工类,已经很熟悉了,我们写一个最简单的继承类;

子类“员工-海外类”

类的继承的写法

定义一个类,在这个类的类名后面将父类的类名用“()”括起来,就得到了一个子类,这样的写法也叫做单一继承(还有多重继承)。子类具有和父类一样的属性,一样的方法,譬如,实例化的时候传入姓名和年龄,将直接调用父类的构造函数(因为子类无构造函数)、实例化的子类直接调用父类的方法,也会输出相同的信息;

注意:

Python总是首先查找本类的方法,如果找不到,才会到父类里去查找,如果找到了,就调用子类的方法,父类的方法将不被调用,比如,上例中,子类如果有自己的构造函数,在实例化的时候,将执行子类的构造函数,而不是执行父类的构造函数;子类只继承父类的公有属性和公有方法;还有一种叫法叫做“基类”和“派生类”,也是指的父类和子类的关系;

为什么要用类的继承

在写代码的时候,如果有若干个类具有共同的属性和方法,那么可以将相同的属性和方法提取出来,整理成一个父类,不同的属性和方法封装在自己的类中使用,则在调用的时候,共同的方法只需要调用父类的方法,就可以实现其目的,简化了代码段,增强了可阅读性,也提高了代码的扩展性;

但是,如果一味的定义父类,父类下面继承子类,子类下面再继承子类,这样就会造成继承的链条非常的长,当代码有一点改动,有可能就会造成弥漫性的改动,所以,尽量不要做过多的继承关系;

子类怎么调用父类的方法

如果子类要调用父类的构造函数方法,可以通过下面的方式实现:

子类调用父类的构造方法

通过使用ParentClass.__init__(self,参数1,参数2........)或者super(childClass, self).__init__(参数1,参数2........)都可以调用父类的构造函数方法,

注意:

子类调用父类构造方法时,参数必须一一对应上,否则会报错;第二种方法不支持多重继承,所以尽量使用第一种;

如果子类要调用父类的普通方法,我们看一下下面这个例子:

子类调用父类的普通方法

通过ParentClass.方法(self)或者self.方法()都可以在子类中使用父类的方法,

请注意self的位置!

多重继承

一个子类继承多个父类,这样的继承就叫做多重继承,它的写法是:class 子类(父类1,父类3,父类3...):在多重继承下,子类将继承所有父类的公有变量和公有方法,即在外面访问时,可以直接访问所有父类的公有变量和公有方法,我们用一个简单的例子来说明:

多重继承

注意:

如果不明确指出,子类将调用第一个父类的构造方法,不会再调用其他父类的构造方法,一般的方法也遵循这种原则(如果方法名称都一样的话);

小结

继承这种思想在面向对象的编程中好处多多,简化代码结构,使扩展性变强,但是,初学者要尽量避免复杂的继承关系,避免把自己绕进去。今天就到这里了,谢谢大家!

Python读书笔记25(类的继承) 互联网视频课程

img

阿一哥

关注

谈类的使用,怎能缺失类的继承!类的继承可以大大简化代码编辑工作。

为啥这么说呢!

因为一个类继承另外一个类的时候,可以自动获得另一个类的所有属性和方法!

原有的类称之为父类,而新的类称之为子类。

子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。

一、类的继承

我们依旧用人举例,先定义一个父类!

这个people类有姓名、姓名、年龄三个属性,接下来我们想定义一个学生类,学生肯定属于人,我们让学生这个类继承people父类。

class Student(People): #定义子类的名字,将父类名字写在括号内

def __init__(self,name,garment): #使用init将父类所有参数传到这里

super().__init__(name,garment) #super()函数将参数赋值给子类

PS:上述代码红色为可变,蓝色为不可变!

我们通过案例可以发现,当student类继承people类后。所有people类的方法student都可以使用,这样可以大家简化代码。

二、单独定义子类的属性和方法

在定义子类的时候,直接添加新的属性即可,本案例添加的是学校这个属性。有些时候父类的有些属性不是我们想要的,那我们还可以重写父类的属性!

三、重写父类方法

当我们想重写父类的方法的时候,就在子类中定义一个和父类一模一样的方法,然后将运行方式和结果更改即可!

换言之,当子类和父类的方法名一致时,子类将覆盖父类的方法!

就酱~类的导入就不分享了,感兴趣的可以自行查询文档,但是没啥用,因为我们不做工程开发的,基本上用不上。

读写文件也不分享了,因为接下来马上要分享的是更好用的pandas,使用pandas读取文件来的更爽!

接下来将分享实战应用最强的数据分析包! pandas!

不见不散!

学Python要学那些东西,可以往什么方向发展 流量视频课程

img

冰松鼠

关注

学习Python的这几天来,觉得Python还是比较简单,容易上手的,就基本语法而言,但是有些高级特性掌握起来还是有些难度,需要时间去消化。Python给我最大的印象就是简洁,这也正是我为什么要从Java转行Python的原因之一。

一、Python简介

ython实现强势逆袭,而且我相信,随着时间的推移,国内Python语言未来前景也是一片向好。

Python的特点是优雅简单,易学易用(虽然我感觉还是有一些概念不容易理解),Python的哲学是尽量用最少的,最简单易懂的代码实现需要的功能。Python适宜于开发网络应用,脚本写作,日常简单小工具等等。Python的缺点是效率较低,但是在大量的场合效率却不是那么重要或者说Python不是其性能瓶颈,所以不要太在意。其次是2.x-3.x的过渡使得许多3.x还缺少很多2.x下的模块,不过也在完善中。其次就是源代码无法加密,发布Python程序其实就是发布源代码。

tiobe编程语言排行榜

一,函数

1.函数是对象,函数名即是指向对应函数对象的引用,所以可以将函数名赋给一个变量,相当于给函数起一个‘别名’。

2.Python函数可以返回”多个值“,之所以打引号,是因为实际上返回的多个值拼成了一个元组,返回这个元组。

3.定义默认参数需要牢记:默认参数必须指向不变对象。否则第一次调用和第二次调用结果会不一样,因为可变的默认参数调用后改变了。

4.可变参数:传入的参数个数是可变的,可以是0个或多个。可变参数会将你传入的参数自动组装为一个tuple。在你传入的list或tuple名字前加一个 * 即说明传入的是可变参数。习惯写法为*args。

5.关键字参数:传入0个或多个含参数名的参数,这些参数被自动组装成一个dict。习惯写法**kw,如**a表示把a中所有的键值对以关键字参数的形式传入kw,获得一个dict,这个dict是a的一份拷贝,对kw改动不会传递到a

6.命名关键字在函数定义中跟在一个*分割符后c,d为命名关键字参数,可以限制调用者可以传入的参数名,同时可以提供默认值

7.参数定义顺序:必选参数,默认参数,可变参数/命名关键字参数,关键字参数。

8.切片操作格式为lis[首下标:尾下标:间隔],如果都不填,即lis[::]则代表整个容器lis

9.用圆括号()括起来一个列表生成式创建一个生成器generator,generator保存生成算法,我们可以用next(g)取得生成器g的下一个返回值。生成器的好处就是我们不需要提前生成所有列表元素,而是需要时再生成,这在某些情况下可以节省许多内存。算法也可以不是列表生成式而是自定义函数,只需在函数定义中包含yield关键字。

10.map()和reduce(): 二者都是高阶函数。map()接收两个参数,一个是函数,一个是Iterable序列,map将传入的函数依次作用在序列每一个元素上,并把结果作为新的Iterator返回。reduce()类似累积计算版的map(),把一个函数作用在一个序列上,每次接收两个参数,将结果继续与序列的下一个元素做累积计算。

利用map和reduce编写一个str2float函数,如把字符串'123.456'转换成浮点数123.456:

11.fliter()函数过滤序列,类似于map()作用于每一元素,根据返回值是True或者False决定舍弃还是保留该元素。函数返回一个Iterator。

12.sorted()函数可实现排序,类似于C++库中的sort()函数,但是比其更加简洁,语法为sorted(lis,key=func,reverse=T/F)

key函数可实现自定义的排序规则,reverse表示升序还是降序。

13.一个函数可以返回一个函数,但是返回时该函数并未执行,所以返回函数中不要引用任何可能发生变化的变量,否则会出现逻辑错误。

14.装饰器(decorator): 当需要增强函数的功能却不希望修改函数本身,那么可以采用装饰器这种运行时动态增加功能的方式,增加的功能卸载装饰器函数中。如在执行前后打印'begin call'和'end call',可以这样做:

二,基础

1.如果一个字符串中有许多需要转义的字符,而又不想写那么多'',那么可以用 r'...' 表示 '...'内的内容不转义。

2.Python的逻辑运算and, or, not 分别对应C语言中的&&, ||, !.

3.Python的整数与浮点数大小都没有范围。

4.Python中除法有两种: '/'除出来必是浮点数, '//'除出来是整数,即地板除。

5.Python中一切皆引用。每个对象都有一个引用计数器(内部跟踪变量)进行跟踪,引用计数值表示该对象有多少个引用,当初次产生赋给变量时,引用计数为1,其后没进行下列行为中的任意一种都会增加引用计数

6.深拷贝与浅拷贝的概念与对比,有点复杂,看这篇文章

7.list,tuple和dict,set

list: 为列表,是一个有序集合,类似于数组但又比数组功能强大,可以随时append,pop元素,下标从0开始,且下标为加n模n制,即lis[-1] = lis[len-1],下标范围[-len,len-1].

tuple:为元组,类似于list,但list为可变类型,而tuple不可变,即没有append,pop等函数。一个建议是为了安全起见,能用tuple代替list尽量用tuple。如果tuple只有一个元素,要写成如(1,)以避免歧义。

dict:字典类型,存放key-value键值对,可以根据key迅速地找出value,当然,key必须是不可变类型

三,面向对象编程

1.Python实例变量可以自由地绑定任何属性

2.为了不让内部属性不被外部访问,在属性的名称前加上两个下划线__,这样就变成了一个私有变量(private),注意,不能直接访问不代表一定不能访问,事实上,加双下划线后Python就会将其改名为‘_class名__name’,所以还是可以这样来访问这个‘私有’变量。

3.对于静态语言,如果要求传入一个class类型的对象,那么传入的对象必须是class类型或者其子类,否则将无法调用class中的方法,而Python这样的动态语言有‘鸭子类型’一说,即不一定要传入class类型或其子类,而只要保证传入的对象中有要使用的方法即可。

4.如果想要限制实例可以绑定的属性,那么在定义class时定义一个__slots__变量即可。

5.@ property装饰器可以使一个getter方法变成属性,如果方法名为me,那么@me.setter装饰器则可使一个setter方法变成属性。这样可以使代码更简短,同时可对参数进行必要的检查。注意,__slots__限制的属性对当前类实例起完全限制作用,且与子类共同定义其__slots__,也就是说子类可以定义自己的__slots__,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__,即并集。

6.通过多重继承,可使子类拥有多个父类的所有功能。

7.在类中__call__方法可使实例对象像函数那样直接调用,作用即是该方法定义的过程。

8.ORM(Object Relational Mapping 对象关系映射),就是把关系数据库的一行映射为一个对象,也就是一个类对应一个表。ORM的实现需要通过metaclass元类修改类的定义。元类可以改变类创建时的行为。

四,IO编程

1.序列化: 把变量从内存中变成可存储或传输的过程称之为序列化。Python用pickle模块实现序列化。序列化之后,就可以把序列化后的内容存储到磁盘上或者通过网络进行传输。pickle.dumps()将对象序列化成一个bytes,而pickle.loads()可以根据bytes反序列化出对象。

2.pickle虽好,但是它专为Python而生,所以要在不同语言间传递对象,最好还是xml或者json,而json表示格式是一个字符串,更易读取,且比xml快,所以更加适宜于对象序列化。Python内置了json模块,相应方法仍然是dumps()和loads()。

3.但是在默认情况下,有些对象是无法序列化的,所以我们有时还需要定制转换方法,告诉json该如何将某类对象转换成可序列为json格式的{}对象。如下即是一个转换方法:

五,调试

1.Python调试方法:

(1)直接打印

(2)断言

(3)pdb

(4)IDE

想学习从事Python工作的请关注小编

Python代码风格:PEP8规则 笔记 互联网视频课程

img

Hasana

关注

Python程序设计的代码风格应该遵循PEP8规则:

一、代码布局

1、缩进:

每级缩进4个空格(不用Tab,更不空格Tab混用)

1、续行应该与其包裹元素对齐,要么使用圆括号、方括号和花括号内的隐式行连接来垂直对齐,要么使用悬挂式缩进对齐。当使用悬挂缩进时,应该考虑到第一行不应该有参数,以及使用缩进以区分自己是续行。

2、缩进4个空格的规则对于续行是可选的。

3、当 if 语句的条件部分长到需要换行写的时候,注意可以在两个字符关键字的连接处(比如 if ),增加一个空格,再增加一个左括号来创造一个4空格缩进的多行条件。这会与 if 语句内同样使用4空格缩进的代码产生视觉冲突。PEP没有明确指明要如何区分i发的条件代码和内嵌代码。可使用的选项包括但不限于下面几种情况:

4、(可以参考下面关于是否在二进制运算符之前或之后截断的讨论)

在多行结构中的大括号/中括号/小括号的右括号可以与内容对齐单独起一行作为最后一行的第一个字符,如:

或者也可以与多行结构的第一行第一个字符对齐,如:

2、Tab还是空格?

空格是被首先推荐的缩进方式。

Tab应该只在现有代码已经使用tab进行缩进的情况下使用,以便和现有代码保持一致。

Python 3不允许再同一个代码块中Tab和空格混合使用。

混合使用制表符和空格缩进的Python2代码应该统一转成空格。

使用命令行运行Python 2时,使用-t选项,会出现非法混用tab和空格的警告。当使用-tt选项时,这些警告会变成错误。强烈推荐使用这些选项!

3、最大行长

每行最大长度79个字符。

对于连续大段的文字(比如文档字符串(docstring)或注释),每行应该被限制在72个字符长度内。

Python标准库比较传统,将行长限制在79个字符以内(文档字符串/注释为72个字符)。

一种推荐的换行方式是利用Python圆括号、方括号和花括号中的隐式续行。长行可以通过在括号内换行来分成多行。应该最好加上反斜杠来区别续行。

有时续行只能使用反斜杠才。例如,较长的多个 with 语句不能采用隐式续行,只能接受反斜杠表示换行:

另一个这样的例子是assert语句。要确保续行的缩进适当。

在二元运算符之前应该换行吗?

遵循数学的传统能产出更多可读性高的代码:

4、空行

顶层函数和类的定义,前后用两个空行隔开。

类里的方法定义用一个空行隔开。

相关的功能组可以用额外的空行(尽量少地)隔开。一堆相关的单行代码之间的空白行可以省略(例如,一组虚拟实现 dummy implementations)。

在函数中使用空行来区分逻辑段(尽量少地)。

Python接受control-L(即^L)换页符作为空格;许多工具把这些字符当作页面分隔符,所以你可以在文件中使用它们来分隔相关段落。请注意,一些编辑器和基于Web的代码阅读器可能无法识别control-L为换页,将在其位置显示另一个字形。

5、源文件编码

Python核心发布版本中的代码总是以UTF-8格式编码(或者在Python2中用ASCII编码)。

使用ASCII(Python 2)或者UTF-8(Python 3)的文件不应该添加编码声明。

在标准库中,只有用作测试目的,或者注释或文档字符串需要提及作者名字而不得不使用非ASCII字符时,才能使用非默认的编码。否则,在字符串文字中包括非ASCII数据时,推荐使用\x, \u, U或N等转义符。

对于Python 3.0及其以后的版本中,标准库遵循以下原则(参见PEP 3131):Python标准库中的所有标识符都必须只采用ASCII编码的标识符,在可行的条件下也应当使用英文词(很多情况下,使用的缩写和技术术语词都不是英文)。此外,字符串文字和注释应该只包括ASCII编码。只有两种例外:

(a) 测试情况下为了测试非ASCII编码的特性

(b) 作者名字。作者名字不是由拉丁字母组成的也必须提供一个拉丁音译名。

鼓励面向全球的开源项目都采用类似的原则。

6、导入

1、imports应该分行写,而不是都写在一行,例如:

这样写也是可以的:

导入(import)始终在文件的顶部,在模块注释和文档字符串之后,在模块全局变量和常量之前。

导入顺序如下:

imports应该按照下面的顺序分组来写:

1、标准库imports

2、相关第三方imports

3、本地应用/库的特定imports

不同组的imports之前用空格隔开。

将任何相关的 __all__ 说明(specification)放在imports之后。

推荐使用绝对(absolute)imports,因为这样通常更易读,在import系统没有正确配置的情况下,也会有更好的表现(或者至少会给出错误信息):

在绝对路径比较长的情况下,也可以使用相对导入:

Python 3中已经禁止隐式的相对导入。

导入类的方法,通常可以这样写:

如果和本地命名的拼写产生了冲突,应当使用绝对导入:

禁止使用通配符导入。

通配符导入(from import *)应该避免,因为它不清楚命名空间有哪些名称存,混淆读者和许多自动化的工具。唯一的例外是重新发布对外的API时可以考虑使用。

7、模块中前后具有双下划线的变量名

像__all__ , __author__ , __version__ 等这样的模块中的变量名(也就是名字里有两个前缀下划线和两个后缀下划线),应该放在文档字符串的后面,以及除from __future__ 之外的import表达式前面。Python要求将来在模块中的导入,必须出现在除文档字符串之外的其他代码之前。

比如:

二、字符串引号

Python中单引号字符串和双引号字符串都是相同的。注意尽量避免在字符串中的反斜杠以提高可读性。

根据PEP 257, 三个引号都使用双引号。

三、表达式和语句中的空格

在下列情况下,避免使用无关的空格:

1、紧跟在小括号,中括号或者大括号后。

2、紧贴在逗号、分号或者冒号之前。

3、然而,冒号在切片中就像二元运算符,在两边应该有相同数量的空格(把它当做优先级最低的操作符)。在扩展的切片操作中,所有的冒号必须有相同的间距。例外情况:当一个切片参数被省略时,空格就被省略了。

4、紧贴在函数参数的左括号之前。

5、紧贴索引或者切片的左括号之前。

6、为了和另一个赋值语句对齐,在赋值运算符附件加多个空格。

其他建议

1、避免在尾部添加空格。因为尾部的空格通常都看不见,会产生混乱:比如,一个反斜杠后面跟一个空格的换行符,不算续行标记。有些编辑器不会保留尾空格,并且很多项目(像CPython)在pre-commit的挂钩调用中会过滤掉尾空格。

总是在二元运算符两边加一个空格:赋值(=),增量赋值(+=,-=),比较(==,,!=,,=,in,not,in,is,is not),布尔(and, or, not)。

如果使用具有不同优先级的运算符,请考虑在具有最低优先级的运算符周围添加空格。有时需要通过自己来判断;但是,不要使用一个以上的空格,并且在二元运算符的两边使用相同数量的空格。

2、在指定函数 关键字参数 或者 默认参数 值的时候,不要在=附近加上空格。

3、功能型注释应该使用冒号的一般性规则,并且在使用 ->的时候要在两边加空格。(参考下面的功能注释得到能够多信息)

4、当给有类型备注的参数赋值的时候,在=两边添加空格(仅针对那种有类型备注和默认值的参数)。

5、复合语句(同一行中的多个语句)通常是不允许的。

6、虽然有时候将小的代码块和 if/for/while 放在同一行没什么问题,多行语句块的情况不要这样用,同样也要避免代码行太长!

四、注释

与代码自相矛盾的注释比没注释更差。修改代码时要优先更新注释!

注释是完整的句子。如果注释是断句,首字母应该大写,除非它是小写字母开头的标识符(永远不要修改标识符的大小写)。

如果注释很短,可以省略末尾的句号。注释块通常由一个或多个段落组成。段落由完整的句子构成且每个句子应该以点号(后面要有两个空格)结束,并注意断词和空格。

非英语国家的程序员请用英语书写你的注释,除非你120%确信代码永远不会被不懂你的语言的人阅读。

1、注释块

注释块通常应用在代码前,并和这些代码有同样的缩进。每行以 '# '(除非它是注释内的缩进文本,注意#后面有空格)。

注释块内的段落用仅包含单个 '#' 的行分割。

2、行内注释

慎用行内注释(Inline Comments) 节俭使用行内注释。 行内注释是和语句在同一行,至少用两个空格和语句分开。行内注释不是必需的,重复罗嗦会使人分心。

不推荐:

但是有时,很有必要:

加了以后对理解代码很有帮助的情况下,关键处才加。

3、文档字符串

文档字符串的标准参见:PEP 257。

为所有公共模块、函数、类和方法书写文档字符串。非公开方法不一定有文档字符串,建议有注释(出现在 def 行之后)来描述这个方法做什么。

更多参考:PEP 257 文档字符串约定。注意结尾的 """ 应该单独成行,例如:

单行的文档字符串,结尾的 """ 在同一行。

4、版本标签

如果你必须在源文件中包含git、Subversion、CVS或RCS crud信息,放置在模块的文档字符串之后,任何其他代码之前,上下各用一个空行:

五、命名规范

Python库的命名约定有点混乱,不可能完全一致。但依然有些普遍推荐的命名规范的。新的模块和包 (包括第三方的框架) 应该遵循这些标准。对不同风格的已有的库,建议保持内部的一致性。

1、最重要的原则

用户可见的API命名应遵循使用约定而不是实现。

2、命名风格

以下是常见的命名方式:

b(单个小写字母)

B(单个大写字母)

lowercase (小写字母)

lower_case_with_underscores (使用下划线分隔的小写字母)

UPPERCASE( 大写字母)

UPPER_CASE_WITH_UNDERSCORES (使用下划线分隔的大写字母)

CapitalizedWords(首字母大写的单词串或驼峰缩写)

注意: 使用大写缩写时,缩写使用大写字母更好。故 HTTPServerError 比 HttpServerError 更好。

mixedCase(不同于首字母大写,第一个单词的首字母小写)

Capitalized_Words_With_Underscores(带下划线,首字母大写,巨丑无比)

还有一种风格使用短前缀分组名字。这在Python中不常用, 但出于完整性提一下。例如,os.stat()返回的元组有st_mode, st_size, st_mtime等等这样的名字(与POSIX系统调用结构体一致)。

X11库的所有公开函数以X开头, Python中通常认为是不必要的,因为属性和方法名有对象作前缀,而函数名有模块名为前缀。

下面讲述首尾有下划线的情况:

_single_leading_underscore:(单前置下划线): 弱内部使用标志。 例如"from M import " 不会导入以下划线开头的对象。

single_trailing_underscore_(单后置下划线): 用于避免与 Python关键词的冲突。 例如:

__double_leading_underscore(双前置下划线): 当用于命名类属性,会触发名字重整。 (在类FooBar中,__boo变成 _FooBar__boo)。

__double_leading_and_trailing_underscore__(双前后下划线):用户名字空间的魔法对象或属性。例如:__init__ , __import__ or __file__,不要自己发明这样的名字。

3、命名约定规范

避免采用的名字:

决不要用字符'l'(小写字母el),'O'(大写字母oh),或 'I'(大写字母eye) 作为单个字符的变量名。一些字体中,这些字符不能与数字1和0区别。用'L' 代替'l'时。

包和模块名:

模块名要简短,全部用小写字母,可使用下划线以提高可读性。包名和模块名类似,但不推荐使用下划线。

模块名对应到文件名,有些文件系统不区分大小写且截短长名字,在 Unix上不是问题,但当把代码迁移到 Mac、Windows 或 DOS 上时,就可能是个问题。当然随着系统的演进,这个问题已经不是经常出现。

另外有些模块底层用C或C++ 书写,并有对应的高层Python模块,C/C++模块名有一个前置下划线 (如:_socket)。

类名:

遵循CapWord。

接口需要文档化并且可以调用时,可能使用函数的命名规则。

注意大部分内置的名字是单个单词(或两个),CapWord只适用于异常名称和内置的常量。

异常名:

如果确实是错误,需要在类名添加后缀 "Error"。

全局变量名:

变量尽量只用于模块内部,约定类似函数。

对设计为通过 "from M import " 来使用的模块,应采用 __all__ 机制来防止导入全局变量;或者为全局变量加一个前置下划线。

函数名:

函数名应该为小写,必要时可用下划线分隔单词以增加可读性。 mixedCase(混合大小写)仅被允许用于兼容性考虑(如: threading.py)。

函数和方法的参数:

实例方法第一个参数是 'self'。

类方法第一个参数是 'cls'。

如果函数的参数名与保留关键字冲突,通常在参数名后加一个下划线。

方法名和实例变量:

同函数命名规则。

非公开方法和实例变量增加一个前置下划线。

为避免与子类命名冲突,采用两个前置下划线来触发重整。类Foo属性名为__a, 不能以 Foo.__a访问。(执著的用户还是可以通过Foo._Foo__a。) 通常双前置下划线仅被用来避免与基类的属性发生命名冲突。

常量:

<...

python面向对象三大特性之继承 流量视频课程

img

周媚颜

关注

继承

目标

单继承 多继承

面向对象三大特性

封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中继承 实现代码的重用,相同的代码不需要重复的编写多态 不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度

01. 单继承

1.1 继承的概念、语法和特点

继承的概念:子类 拥有 父类 的所有 方法 和 属性

1) 继承的语法

```python

class 类名(父类名):

pass

```

子类 继承自 父类,可以直接 享受 父类中已经封装好的方法,不需要再次开发

子类 中应该根据 职责,封装 子类特有的 属性和方法

2) 专业术语

`Dog` 类是 `Animal` 类的子类,`Animal` 类是 `Dog` 类的父类,`Dog` 类从 `Animal` 类继承

`Dog` 类是 `Animal` 类的派生类,`Animal` 类是 `Dog` 类的基类,`Dog` 类从 `Animal` 类派生

3) 继承的传递性

`C` 类从 `B` 类继承,`B` 类又从 `A` 类继承

那么 `C` 类就具有 `B` 类和 `A` 类的所有属性和方法

子类 拥有 父类 以及 父类的父类 中封装的所有 属性 和 方法

提问

哮天犬 能够调用 `Cat` 类中定义的 `catch` 方法吗?

答案

不能,因为 哮天犬 和 `Cat` 之间没有 继承 关系

1.2 方法的重写

子类 拥有 父类 的所有 方法 和 属性

子类 继承自 父类,可以直接 享受 父类中已经封装好的方法,不需要再次开发

应用场景

当 父类 的方法实现不能满足子类需求时,可以对方法进行 重写(override)

重写 父类方法有两种情况:

覆盖 父类的方法对父类方法进行 扩展

1) 覆盖父类的方法

如果在开发中,父类的方法实现 和 子类的方法实现,完全不同

就可以使用 覆盖 的方式,在子类中 重新编写 父类的方法实现

> 具体的实现方式,就相当于在 子类中 定义了一个 和父类同名的方法并且实现

重写之后,在运行时,只会调用 子类中重写的方法,而不再会调用 父类封装的方法

2) 对父类方法进行 扩展

如果在开发中,子类的方法实现 中 包含 父类的方法实现

父类原本封装的方法实现 是 子类方法的一部分

就可以使用 扩展 的方式

在子类中 重写 父类的方法在需要的位置使用 `super().父类方法` 来调用父类方法的执行代码其他的位置针对子类的需求,编写 子类特有的代码实现

关于 `super`

在 `Python` 中 `super` 是一个 特殊的类

`super()` 就是使用 `super` 类创建出来的对象

最常 使用的场景就是在 重写父类方法时,调用 在父类中封装的方法实现

调用父类方法的另外一种方式(知道)

> 在 `Python 2.x` 时,如果需要调用父类的方法,还可以使用以下方式:

```python

父类名.方法(self)

```

这种方式,目前在 `Python 3.x` 还支持这种方式

这种方法 不推荐使用,因为一旦 父类发生变化,方法调用位置的 类名 同样需要修改

提示

在开发时,`父类名` 和 `super()` 两种方式不要混用

如果使用 当前子类名 调用方法,会形成递归调用,出现死循环

1.3 父类的 私有属性 和 私有方法

子类对象 不能 在自己的方法内部,直接 访问 父类的 私有属性 或 私有方法子类对象 可以通过 父类 的 公有方法 间接 访问到 私有属性 或 私有方法

> 私有属性、方法 是对象的隐私,不对外公开,外界 以及 子类 都不能直接访问

> 私有属性、方法 通常用于做一些内部的事情

示例

`B` 的对象不能直接访问 `__num2` 属性

`B` 的对象不能在 `demo` 方法内访问 `__num2` 属性

`B` 的对象可以在 `demo` 方法内,调用父类的 `test` 方法

父类的 `test` 方法内部,能够访问 `__num2` 属性和 `__test` 方法

02. 多继承

概念

子类 可以拥有 多个父类,并且具有 所有父类 的 属性 和 方法

例如:孩子 会继承自己 父亲 和 母亲 的 特性

语法

```python

class 子类名(父类名1, 父类名2...)

pass

``

2.1 多继承的使用注意事项

问题的提出

如果 不同的父类 中存在 同名的方法,子类对象 在调用方法时,会调用 哪一个父类中的方法呢?

> 提示:开发时,应该尽量避免这种容易产生混淆的情况! —— 如果 父类之间 存在 同名的属性或者方法,应该 尽量避免 使用多继承

Python 中的 MRO —— 方法搜索顺序(知道)

`Python` 中针对 类 提供了一个 内置属性 `__mro__` 可以查看 方法 搜索顺序

MRO 是 `method resolution order`,主要用于 在多继承时判断 方法、属性 的调用 路径

```python

print(C.__mro__)

```

输出结果

```

(,,,)

```

在搜索方法时,是按照 `__mro__` 的输出结果 从左至右 的顺序查找的

如果在当前类中 找到方法,就直接执行,不再搜索

如果 没有找到,就查找下一个类 中是否有对应的方法,如果找到,就直接执行,不再搜索

如果找到最后一个类,还没有找到方法,程序报错

2.2 新式类与旧式(经典)类

> `object` 是 `Python` 为所有对象提供的 基类,提供有一些内置的属性和方法,可以使用 `dir` 函数查看

新式类:以 `object` 为基类的类,推荐使用

经典类:不以 `object` 为基类的类,不推荐使用

在 `Python 3.x` 中定义类时,如果没有指定父类,会 默认使用 `object` 作为该类的 基类 —— `Python 3.x` 中定义的类都是 新式类

在 `Python 2.x` 中定义类时,如果没有指定父类,则不会以 `object` 作为 基类

> 新式类 和 经典类 在多继承时 —— 会影响到方法的搜索顺序

为了保证编写的代码能够同时在 `Python 2.x` 和 `Python 3.x` 运行!

今后在定义类时,如果没有父类,建议统一继承自 `object`

```python

class 类名(object):

pass

```

python面向对象三大特性之多态 营销视频课程

img

外星人

关注

多态

目标

多态

面向对象三大特性

1. 封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中

定义类的准则

2. 继承 实现代码的重用,相同的代码不需要重复的编写

设计类的技巧

子类针对自己特有的需求,编写特定的代码

3. 多态 不同的 子类对象 调用相同的 父类方法,产生不同的执行结果

多态 可以 增加代码的灵活度

以 继承 和 重写父类方法 为前提

是调用方法的技巧,不会影响到类的内部设计

多态案例演练

需求

1. 在 `Dog` 类中封装方法 `game`

普通狗只是简单的玩耍

2. 定义 `XiaoTianDog` 继承自 `Dog`,并且重写 `game` 方法

哮天犬需要在天上玩耍

3. 定义 `Person` 类,并且封装一个 和狗玩 的方法

在方法内部,直接让 狗对象 调用 `game` 方法

案例小结

`Person` 类中只需要让 狗对象 调用 `game` 方法,而不关心具体是 什么狗

`game` 方法是在 `Dog` 父类中定义的

在程序执行时,传入不同的 狗对象 实参,就会产生不同的执行效果

> 多态 更容易编写出出通用的代码,做出通用的编程,以适应需求的不断变化

```python

class Dog(object):

def __init__(self, name):

self.name = name

def game(self):

print("%s 蹦蹦跳跳的玩耍..." % self.name)

class XiaoTianDog(Dog):

def game(self):

print("%s 飞到天上去玩耍..." % self.name)

class Person(object):

def __init__(self, name):

self.name = name

def game_with_dog(self, dog):

print("%s 和 %s 快乐的玩耍..." % (self.name, dog.name))

让狗玩耍

dog.game()

1. 创建一个狗对象

wangcai = Dog("旺财")

wangcai = XiaoTianDog("飞天旺财")

2. 创建一个小明对象

xiaoming = Person("小明")

3. 让小明调用和狗玩的方法

xiaoming.game_with_dog(wangcai)

img

在线咨询

建站在线咨询

img

微信咨询

扫一扫添加
动力姐姐微信

img
img

TOP