赞
踩
Python是完全面向对象的语言
函数、模块、数字、字符串都是对象,在Python中一切皆对象
完全支持继承、重载、多重继承
支持重载运算符,也支持泛型设计
拥有一个强大的标准库
Python 语言的核心只包含数字、字符串、列表、字典、文件等常见类型和函数,而由Python标准库提供了系统管理、网络通信、文本处理、数据库接口、图形系统、XML 处理等额外的功能.
Python社区提供了大量的第三方模块,使用方式与标准库类似
它们的功能覆盖科学计算、人工智能、机器学习、Web 开发、数据库接口、图形系统 多个领域.
编译(静态语言):程序在执行之前需要一个专门的编译过程,把程序编译成为机器语言的文件,运行时不需要重新翻译,直接使用编译的结果就行了。程序执行效率高,依赖编译器,跨平台性差些。如 C、C++、java
解释(脚本语言):以文本方式存储程序代码,会将代码一句一句直接运行。在发布程序时,看起来省了道编译工序,但是在运行程序的时候,必须先解释再运行(将源代码逐条翻译成目标代码同时逐条运行),如Python 、Java Script、PHP
(1)解释器python/python3
Python 2.x 使用的解释器是 ipython
Python 3.x 使用的解释器是 ipython3
(2)交互式运行Python程序:对每个输入语句即时运行结果
默认:python shell
优点:适合于学习/验证 Python 语法或者局部代码
缺点:•代码不能保存
•不适合运行太大的程序
IPython:◦支持自动补全
◦自动缩进
◦支持 bash shell 命令
◦内置了许多很有用的功能和函数
退出解释器:①直接输入 exit②按热键 ctrl + d,IPython 会询问是否退出解释器
(3)Python的IDE - PyCharm:文件式编程,批量处理一组语句并运行结果,这是编程的主要方式
集成开发环境:图形用户界面、代码编辑器(支持代码补全/自动缩进)、编译器/解释器、调试器(断点/单步执行)
(4)cmd运行python脚本
前置条件:先在windows设置python环境变量
进入cmd:
首先下载安装好python,命令行判断:
python是否安装成功和安装版本:输入python
检查是否安装了pip:输入pip
注意配置好环境变量(Python安装地址)。
环境变量分为系统环境变量和用户环境变量。
正常所说的环境变量是指系统环境变量,对所有用户起作用,而用户环境变量只对当前用户起作用,如果此电脑登入了另外个用户账号,那配置之前账号的用户环境变量就对另外个用户账号不起作用。
优先级高低是:系统变量 > 用户变量。也就是说,环境变量设置相同,先在系统变量里面找,找不到再到用户变量里面去找。
而在一个环境变量里面,如果有多个值,优先级是最前面的或者最上面的项优先级高。比如在Path环境变量里面,同时设置了python2.7和python3.6的路径,结果是先设置的起作用,这对于切换使用不同版本的软件比较方便,只需要上移/下移就行。
举例:
Python和pip环境变量,添加到path:
C:\Program Files\Python380
C:\Program Files\Python380\Scripts
pip
pip <command> [options]
进入cmd,输入pip,可以查看所有指令。
常用指令:
pip install package-name,用pip来安装第三方的包
- pip install -r requirements.txt 的作用是从一个文本文件 requirements.txt 中安装所需的 Python 包。一般情况下,项目提供者会在 requirements.txt 文件中列出所有项目所依赖的 Python 包及其版本号,使用这个命令可以方便地安装这些依赖并满足项目运行的需要。
pip install matplotlib==3.4.1,安装指定版本的第三方的包
pip uninstall package_name,卸载某个包
pip install --upgrade package_name# 或者是pip install -U package_name,更新某个包
pip show -f requests,查看指定包的信息
pip list -o 查看需要被升级的包
pip list 查看当前项目安装的包
概念:变量是用来保存和表示数据的占位符号
每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建
创建一个变量,包括
使用(type)函数可以查看一个变量的类型
整数(int)
%:取余
//:求整除
pow(x,y) :计算x^y
pow(x,y[,z]) : 幂余,x和y是必选参数,z是可选参数;如果使用了参数z,中括号必须去掉,即power(x,y,z),其结果是x的y次方再对z求余数,但是这种方式比power(x,y) % z的执行效率要高
abs(x) : 求绝对值
divmod(x,y), 商余,(x//y,x%y)结果为(商,余)
浮点数(float)
注意:浮点数计算存在不确定性位数,但这不是bug;round(x,d) :对x四舍五入,d是小数截取位数
科学计数法表示: <a>e<b> 表示a*(10^b)
布尔(bool)
“布尔”数据类型只有两种值:True 和False。
◾真 True ,非 0 数
◾假 False ,0
比较操作符
== 等于,!= 不等于,< 小于,> 大于,<= 小于等于,>= 大于等于,比较两个值,求值为一个布尔值。
>>> 42 == 42
True
布尔操作符
①二元布尔操作符
and 和or 操作符总是接受两个布尔值(或表达式),所以它们被认为是“二元”操作符。如果两个布尔值都为True,and 操作符就将表达式求值为True,否则求值为False。另一方面,只要有一个布尔值为真,or 操作符就将表达式求值为True。如果都是False,所求值为False。
>>> True and True
True
>>> True and False
False
>>> print(0 or 1 and True)
True
②not 操作符
not 操作符只作用于一个布尔值(或表达式),not 操作符求值为相反的布尔值。
>>> not True
False
③混合布尔和比较操作符
>>> (4 < 5) and (5 < 6)
True
>>> (4 < 5) and (9 < 6)
False
复数型 (complex)
a+bj ; a-bj
注意:不同数字类型混合运算,结果为“最宽”类型
字符串、列表、元组、字典、set集合,详见以下链接:
Python变量——字符串、列表、元组、字典、set_python 字符串 *-CSDN博客
变量的引用
概念:
•变量 和 数据 是分开存储的
•数据 保存在内存中的一个位置
•变量 中保存着数据在内存中的地址
•变量 中 记录数据的地址,就叫做 引用
•使用 id() 函数可以查看变量中保存数据所在的 内存地址(每次运行脚本时,id会变化)
注意:如果变量已经被定义,当给一个变量赋值的时候,本质上是 修改了数据的引用
•变量 不再 对之前的数据引用
•变量 改为 对新赋值的数据引用
在 Python 中,函数的 实参/返回值 都是是靠 引用 来传递来的
可变和不可变类型
不可见类型,内存中的数据不允许被修改。value(值)一旦改变,id(内存地址)也改变,则称为不可变类型(id变,意味着创建了新的内存空间)。
◦数字类型 int, bool, float, complex, long(2.x)
- #id
- a = 1
- print(id(a),type(a)) #1452422928 <class 'int'>
- a = 2
- print(id(a),type(a)) #1452422944 <class 'int'>
- #float
- b = 1.23
- print(id(b),type(b)) #13260288 <class 'float'>
- b = 2.59
- print(id(b),type(b)) #13260048 <class 'float'>
- #复数型
- c = 1+2j
- print(id(c),type(c)) #17454936 <class 'complex'>
- c = 1-2j
- print(id(c),type(c)) #17455608 <class 'complex'>
- #bool
- d = True
- print(id(d),type(d)) #1452241744 <class 'bool'>
- d = False
- print(id(d),type(d)) #1452241760 <class 'bool'>
◦字符串 str,改变string值后,id也变了
- str = "test string"
- print(id(str)) #17515288
- str = "change"
- print(id(str)) #16472544
◦元组 tuple,改变值后,id也变了
- info_tuple = ("zhangsan", 18, 1.75)
- print(id(info_tuple)) # 15016344
- info_tuple = info_tuple + (1,2,3)
- print(info_tuple)#('zhangsan', 18, 1.75, 1, 2, 3)
- print(id(info_tuple)) #14083496
◦日期
- #日期
- import datetime
- oneday = datetime.date.today()
- print(oneday) #2022-03-23
- print(id(oneday),type(oneday))# 10508792 <class 'datetime.date'>
- oneday = datetime.date.today() - oneday
- print(oneday) #0:00:00
- print(id(oneday),type(oneday)) #10509176 <class 'datetime.timedelta'>
可变类型:在id(内存地址)不变的情况下,value(值)可以变,则称为可变类型
- l = [1,2,3,4,5]
- print(id(l)) # 13642288
- print(l[4]) #5
- l[4] = 9
- print(id(l)) # 13642288
- info = {"name":"Mary","age":"26"}
- print(id(info)) #18251528
- info["name"] = "Cindy"
- print(id(info)) #18251528
- set1={1,2,1,3,4,5,6,7}
- print(id(set1),type(set1))#21787872 <class 'set'>
- set1={1,2,3,8,9,7,10}
- print(id(set1),type(set1))#21787872 <class 'set'>
可变类型的数据变化,是通过 方法 来实现的。如果给一个可变类型的变量,赋值了一个新的数据,引用会修改
•变量 不再 对之前的数据引用
•变量 改为 对新赋值的数据引用
身份运算符
身份运算符用于 比较 两个对象的 内存地址 是否一致 —— 是否是对同一个对象的引用
is:is 是判断两个标识符是不是引用同一个对象,x is y,类似 id(x) == id(y)
is not: is not 是判断两个标识符是不是引用不同对象 ,x is not y,类似 id(a) != id(b)
is 与 == 区别:
is 用于判断 两个变量 引用对象是否为同一个
== 用于判断 引用变量的值 是否相等
哈希 (hash)
Python 中内置有一个名字叫做 hash() 的函数,获取一个对象的哈希值。
◦接收一个 不可变类型 的数据作为 参数(list,dictionary,set都是unhashable type)
◦返回 结果是一个 整数
哈希 是一种 算法,其作用就是提取数据的 特征码(指纹)
◦相同的内容 得到 相同的结果
◦不同的内容 得到 不同的结果
在 Python 中,设置字典的 键值对 时,会首先对 key(字典中的key也是不可变数据类型) 进行 hash 以决定如何在内存中保存字典的数据,以方便后续对字典的操作:增、删、改、查。
- str = "apple"
- print(hash(str)) #-1877658494
- print(hash(1.23)) #579820504
局部变量和全局变量
局部变量:
•局部变量 是在 函数内部 定义的变量,只能在函数内部使用
•函数执行结束后,函数内部的局部变量,会被系统回收
•不同的函数,可以定义相同的名字的局部变量,但是 彼此之间 不会产生影响
作用:在函数内部使用,临时 保存 函数内部需要使用的数据
局部变量的生命周期
•所谓 生命周期 就是变量从 被创建 到 被系统回收 的过程
•局部变量 在 函数执行时 才会被创建
•函数执行结束后 局部变量 被系统回收
•局部变量在生命周期 内,可以用来存储 函数内部临时使用到的数据
全局变量:
全局变量 是在 函数外部定义 的变量,所有函数内部都可以使用这个变量
注意:函数执行时,需要处理变量时 会:
1.首先 查找 函数内部 是否存在 指定名称 的局部变量,如果有,直接使用
2.如果没有,查找 函数外部 是否存在 指定名称 的全局变量,如果有,直接使用
3.如果还没有,程序报错!
注意:
1.函数不能直接修改 全局变量的引用;
•如果在函数中需要修改全局变量,需要使用 global 进行声明
global num
# 只是定义了一个局部变量,不会修改到全局变量,只是变量名相同而已
num = 100
•为了保证所有的函数都能够正确使用到全局变量,应该 将全局变量定义在其他函数的上方
命名规则:
在定义变量时,为了保证代码格式,= 的左右应该各保留一个空格
在 Python 中,如果变量名需要由两个或多个单词组成时,
保留字/关键字(33个)
被编程语言内部定义并保留使用的标识符:and,as,assert,break,class,continue,def,del,elif,else,expect,finally,for,from,False,global,if,is,import,in,lambda,not,nonlocal,None,or,pass,return,raise,try,True,while,with,yeild
标识符/关键字后面不需要使用括号
语法:每个保留字所在行最后存在一个冒号(:),比如def,class后面
算术运算符:+ - * / %(取余) //(整除) ** (求次方)
逻辑运算符:与(and),或(or),非(not)
成员运算符:
\b : 回退
\n : 换行
\r : 回车
\t:横向制表符,在控制台输出一个 制表符,协助在输出文本时 垂直方向 保持对齐
\\:反斜杠符号
\' :单引号
\": 双引号
Python以缩进表达程序的格式框架,所以要严格控制缩进,一般是4个空格,或者一个 tab 键。
注意:在 Python 开发中,Tab 和空格不要混用!
单行注释: # 追加说明文字 注意:尽量在文字前面打个空格 在# 号前面需要追加两个空格。例如 print() # 注释
多行注释语法:
"""
注释内容
"""
面向对象编程 —— Object Oriented Programming 简写 OOP。
面向对象与面向过程:
面向过程 | 面向对象 | |
怎么做 | 1.把完成某一个需求的所有步骤从头到尾逐步实现 2.根据开发需求,将某些功能独立 的代码封装成一个又一个 函数 3.最后完成的代码,就是顺序地调用不同的函数 | 相比较函数,面向对象是更大的封装,根据职责在一个对象中 封装多个方法 1.在完成某一个需求前,首先确定职责 —— 要做的事情(方法) 2.根据职责确定不同的对象,在对象内部封装不同的方法(多个) 3.最后完成的代码,就是顺序地让不同的对象调用不同的方法 |
特点 | 1.注重步骤与过程,不注重职责分工 2.如果需求复杂,代码会变得很复杂 3.开发复杂项目,没有固定的套路,开发难度很大 | 1.注重对象和职责,不同的对象承担不同的职责 2.更加适合应对复杂的需求变化,是专门应对复杂项目开发,提供的固定套路 3.需要在面向过程基础上,再学习一些面向对象的语法 |
面向对象是更大的封装,在一个类中封装多个方法,这样通过这个类创建出来的对象,就可以直接调用这些方法了 |
类是对一群具有相同特征或者行为的事物的一个统称,是抽象的,不能直接使用。
◦特征 被称为属性
◦行为 被称为方法
类名:命名方法:首字母大写
名词提炼法 :分析整个业务流程,出现的名词,通常就是找到的类
属性:对对象的特征描述,通常可以定义成属性
方法:对象具有的行为(动词),通常可以定义成方法。类中的函数称为方法,函数的一切都适用于方法,二者之间有一个重要的差别就是调用方式不同。
定义只包含方法的类:
- class 类名:
- def 方法1(self, 参数列表):
- pass
- def 方法2(self):
- pass
对象是由类创建出来的一个具体存在,可以直接使用。
由哪一个类创建出来的对象,就拥有在哪一个类中定义的属性和方法
创建对象:对象变量 = 类名(),例如:my_dog = Dog()
类是模板,对象是根据类这个模板创建出来的,应该先有类,再有对象
•类 只有一个,而对象可以有很多个
◦不同的对象之间属性可能会各不相同
•类 中定义了什么属性和方法,对象中就有什么属性和方法,不可能多,也不可能少
当使用类名() 创建对象时,会自动执行以下操作:
这个初始化方法就是 __init__ 方法,__init__ 是对象的内置方法(类是一个特殊的对象 —— 类对象,如果不在类中定义def __init__(self),会使用默认的内置方法,如果在类中定义def __init__(self),相当于重构)。__init__ 方法是专门用来定义一个类具有哪些属性的方法。每当根据类创建新实例时,Python都会自动运行这个方法(其他自定义方法需要调用才能使用,要调用方法,可指定实例的名称和要调用的方法:对象.方法名())。
初始化方法__init__ ()开头和末尾有两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。
在开发中,如果希望在创建对象的同时,就设置对象的属性,可以对 __init__ 方法进行 改造
举例1:
- class Cat:
- def __init__(self, name):
- print("初始化方法 %s" % name)
- self.name = name
- tom = Cat("Tom")
- lazy_cat = Cat("大懒猫")
举例2:给属性设置默认值
类中的每个属性都必须有初始值,哪怕这个值是0或空字符串。在方法__init__()中制定这种初始值是可行的;如果你对某个属性这样做了,就无需包含为它提供初始值的形参。
def __init__(self): """初始化游戏的静态设置""" #屏幕设置 self.screen_width = 1200 self.screen_height = 800 self.bg_color = (230,230,230) #飞船设置 self.ship_limit = 3 #子弹设置 self.bullet_width = 3 self.bullet_height = 15 self.bullet_color = 60,60,60 #将未消失的子弹设置为最大为3颗 self.bullets_allowed = 3 #外星人设置 self.fleet_drop_speed = 10 #以什么样的速度加快游戏节奏 self.speed_up_scale = 1.1 #外星人点数的提高速度 self.score_scale = 1.5
方法中的形参self
python调用__init__()来创建实例时,将自动传入实参self。每个与类相关联的方法调用都自动传实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。例如,我们将通过实参向Cat()传递名字和年龄,self会自动传递,因此我们不需要传递它。当我们根据Cat类创建实例时,都只需要给后面的形参(比如:name,age)提供值。
以self为前缀的变量都可以供类中所有的方法使用,我们也可以通过类的任何实例来访问这些变量。
self.name(实参) = name(形参)获取存储在形参name中的值,并将其存储到变量name中,然后该变量被关联到当前创建的实例。像这样可以通过实例访问的变量称为属性。( self.属性 = 形参)
- class Complex:
- def __init__(self, realpart, imagpart):
- self.r = realpart
- self.i = imagpart
- x = Complex(3.0, -4.5)
- print(x.r, x.i)
- #结果:3.0 -4.5
•在类的外部,通过变量名(即对象名). 访问对象的属性和方法
•在类封装的方法中通过self.访问对象的属性和方法
总结:
由哪一个对象调用的方法,方法内的self就是哪一个对象的引用.
self. 调用其他的对象方法举例:
应用场景:
•在实际开发中,对象的某些属性或方法可能只希望在对象的内部被使用,而不希望在外部被访问到
•私有属性就是对象不希望公开的属性
•私有方法就是对象不希望公开的方法
定义方式:在定义属性或方法时,在 属性名或者方法名前增加两下划线,定义的就是私有属性或方法,如:self.__age = 18
①术语:实例
1.创建出来的对象叫做类的实例
2.创建对象的动作叫做实例化
3.对象的属性叫做实例属性
4.对象调用的方法叫做实例方法
②类是一个特殊的对象
Python中一切皆对象
•在程序运行时,类同样会被加载到内存
•在Python中,类是一个特殊的对象 — 类对象
•在程序运行时,类对象在内存中只有一份,使用一个类可以创建出很多个对象实例
•除了封装实例的属性和方法外,类对象还可以拥有自己的属性和方法(类属性和类方法) • 通过 “ 类名. ” 的方式可以 访问类的属性 或者 调用类的方法
③类属性和实例属性
•类属性就是给类对象定义的属性,通常用来记录与这个类相关的特征
•类属性不会用于记录具体对象的特征
④类方法和静态方法
类方法
类方法就是针对类对象定义的方法,在类方法内部可以直接访问类属性或者调用其他的类方法。
类方法和普通方法的区别是,类方法只能访问类变量,不能访问实例变量。
语法:
- @classmethod
- def 类方法名(cls):
- pass
•类方法需要用 修饰器 @classmethod 来标识,告诉解释器这是一个类方法
•类方法的第一个参数应该是 cls
◦由哪一个类调用的方法,方法内的cls就是哪一个类的引用
◦这个参数和实例方法的第一个参数self 类似
◦提示使用其他名称也可以,不过习惯使用 cls
•通过类名. 调用类方法,调用方法时,不需要传递 cls 参数
在方法内部
◦可以通过 cls. 访问类的属性
◦也可以通过 cls. 调用其他的类方法
静态方法
•在开发时,如果需要在类中封装一个方法,这个方法:
◦既不需要访问实例属性或者调用实例方法
◦也不需要访问类属性或者调用类方法
•这个时候,可以把这个方法封装成一个静态方法
语法如下
- @staticmethod
- def 静态方法名():
- pass
•静态方法需要用修饰器 @staticmethod 来标识,告诉解释器这是一个静态方法
•通过类名. 调用静态方法
举例:
- class Dog(object):
- # 狗对象计数
- dog_count = 0
- @staticmethod
- def run():
- # 不需要访问实例属性也不需要访问类属性的方法
- print("狗在跑...")
- def __init__(self, name):
- self.name = name
普通方法、类方法和静态方法对比:
根据人们的惯用用法,self一般是在实例方法中使用,而cls则一般在类方法中使用,在静态方法中则不需要使用一个默认参数;
静态方法和类方法都需要使用修饰器,分别使用的是staticmethod和classmethod;
普通方法不能通过类名调用,但是静态方法和类方法是可以的。普通方法通过对象调用。
面向对象三大特性:继承、封装、多态。
继承,实现代码的重用,相同的代码不需要重复的编写
概念:子类拥有父类的所有方法和属性
语法:•子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发
•子类中应该根据职责,封装子类特有的属性和方法
继承的语法: class 类名(父类名):
术语:Dog 类是 Animal 类的子类,Animal 类是 Dog 类的父类,Dog 类从 Animal 类继承
Dog 类是 Animal 类的派生类,Animal 类是 Dog 类的基类,Dog 类从 Animal 类派生
继承的传递性:子类拥有父类以及父类的父类中封装的所有属性和方法
当父类的方法实现不能满足子类需求时,可以对方法进行重写(override)两种情况:
①覆盖父类的方法
•如果在开发中,父类的方法实现和子类的方法实现完全不同
•就可以使用覆盖的方式,在子类中重新编写父类的方法实现
具体的实现方式,就相当于在子类中定义了一个和父类同名的方法并且实现
重写之后,在运行时,只会调用子类中重写的方法,而不再会调用父类封装的方法
②对父类方法进行扩展
1.在子类中重写父类的方法
2.在需要的位置使用super().父类方法来调用父类方法的执行
3.代码其他的位置针对子类的需求,给子类定义属性和方法,编写子类特有的代码实现
super:•在Python中super是一个特殊的类
•super() 就是使用super类创建出来的对象
•最常使用的场景就是在重写父类方法时,调用在父类中封装的方法实现
super()._init_() 调用父类的方法_init_()
- class Bullet(Sprite):
- """一个对飞船发射的子弹进行管理的类"""
- def __init__(self,ai_settings,screen,ship):
- """在飞船所处的位置创建一个子弹对象"""
- super().__init__()
- self.screen = screen
-
- # 在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
- self.rect = pygame.Rect(0,0,ai_settings.bullet_width,ai_settings.bullet_height)
- self.rect.centerx = ship.rect.centerx
- self.rect.top = ship.rect.top
-
- # 存储用小数表示的子弹位置
- self.y = float(self.rect.y)
-
- self.color = ai_settings.bullet_color
- self.speed_factor = ai_settings.bullet_speed_factor
- def update(self):
- """向上移动子弹"""
- #更新表示子弹位置的小数值
- self.y -= self.speed_factor
- #更新表示子弹的rect位置
- self.rect.y =self.y
- def draw_bullet(self):
- """在屏幕上绘制子弹"""
- pygame.draw.rect(self.screen,self.color,self.rect)
有时候,根据需要,我们可以把很多属性和方法提取出来,放到一个类中。
举例说明:把很多属性和方法另一个类Battery中,并将一个Battery实例用作ElectricCar类的一个属性。
- class Car():
- --snip--
- class Battery():
- def _init_(self,battery_size=70):
- self.battery_size = battery_size
- class ElectricCar(Car):
- def _init_():
- super()._init_(make,model,year)
- #将实例用作属性
- self.battery = Battery()
- my_tesla = ElectricCar('tesla','model s','2018')
1.子类对象不能在自己的方法内部,直接访问父类的私有属性或私有方法
2.子类对象可以通过父类的公有方法间接访问到私有属性或私有方法
•私有属性、方法是对象的隐私,不对外公开,外界以及子类都不能直接访问
•私有属性、方法通常用于做一些内部的事情
概念:子类可以拥有多个父类,并且具有所有父类的属性和方法
例如:孩子会继承自己父亲和母亲的特性
语法:class 子类名(父类名1, 父类名2...)
pass
注意事项:开发时,应该尽量避免容易产生混淆的情况—— 如果 父类之间存在同名的属性或者方法,应该尽量避免使用多继承。
1.封装是面向对象编程的一大特点
2.面向对象编程的第一步—— 将属性和方法封装到一个抽象的类中
3.外界使用类创建对象,然后让对象调用方法
4.对象方法的细节都被封装在类的内部
模块化和参数化:
假设要实现关于126邮箱的自动化测试项目那么可能每条用例都要有登录和退出动作,大部分测试用例都是在登录后进行的,例如:发邮件、查看、删除、搜索邮件等操作。
此时,创建一个module.py文件来存放登录和退出操作(模块化)。测试数据会不同,将login()方法参数化。
- class Mail:
- def __init__(self,driver):
- self.driver = driver
- def login(self,username,password):
- """登录"""
- login_frame = self.driver.find_element_by_css_selector('iframe[id^="x-URS-iframe"]')
- self.driver.switch_to.frame(login_frame)
- self.driver.find_element_by_name("email").clear()
- self.driver.find_element_by_name("email").send_keys("username")
- self.driver.find_element_by_name("password").clear()
- self.driver.find_element_by_name("password").send_keys("password")
- self.driver.find_element_by_id("dologin").click()
- def logout(self):
- """退出"""
- self.driver.find_element_by_link_text("退出").click()
在test_mail.py中,调用Mail类的login()和logout()方法。
- from time import sleep
- from selenium import webdriver
- from module import Mail
-
- driver = webdriver.Chrome()
- driver.get("https://www.126.com/")
- #调用Mail类并接受driver驱动
- mail = Mail(driver)
- #登录账号为空
- mail.login("","")
- #用户名为空
- mail.login("","password")
- #密码为空
- mail.login("username","")
- #用户名/密码错误
- mail.login("error","error")
- #管理员登录
- mail.login("admin","admin123")
-
- #登录之后的操作
- sleep(5)
- #退出
- mail.logout()
- driver.quit()
多态:不同的子类对象 调用相同的父类方法,产生不同的执行结果
•多态可以增加代码的灵活度
•以继承和重写父类方法为前提
•是调用方法的技巧,不会影响到类的内部设计
①概念
模块是 Python 程序架构的一个核心概念
•每一个以扩展名.py 结尾的 Python源代码文件都是一个模块
•模块名同样也是一个标识符,需要符合标识符的命名规则
•在模块中定义的全局变量 、函数、类都是提供给外界直接使用的工具
•模块就好比是工具包,要想使用这个工具包中的工具,就需要先导入这个模块
②模块的两种导入方式
import 导入
提示:在导入模块时,每个导入应该独占一行
import 模块名1
import 模块名2
导入之后 ,通过 模块名. 使用 模块提供的工具——全局变量、函数、类
如果模块的名字太长,可以使用 as 指定模块的名称,以方便在代码中的使用
实现:import 模块名1 as 模块别名 (模块别名应该符合大驼峰命名法)
- import game_functions as gf
- def run_game():
- while True:
- gf.check_events(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets)
- if stats.game_active:
- gf.update_bullets(ai_settings,screen,stats,sb,ship,aliens,bullets)
- gf.update_aliens(ai_settings,screen,sb,ship,aliens,stats,bullets)
- gf.update_screen(ai_settings,screen,stats,sb,ship,aliens,bullets,play_button)
- run_game()
from...import 导入
•如果希望 从某一个模块 中,导入 部分 工具,就可以使用 from ... import 的方式
•import 模块名 是 一次性 把模块中 所有工具全部导入,并且通过 模块名/别名 访问
实现:from 模块名1 import 工具名
导入之后
◦不需要通过模块名.
◦可以直接使用模块提供的工具——全局变量、函数、类
注意:如果两个模块,存在同名的函数,那么后导入模块的函数,会覆盖掉先导入的函数
一旦发现冲突,可以使用 as 关键字 给其中一个工具起一个别名
# 从模块导入所有工具,提示:这种方式不推荐使用,因为函数重名并没有任何的提示,出现问题不好排查
from 模块名1 import *
- from settings import Settings
- from ship import Ship
- def run_game():
- ai_settings = Settings()
- ship = Ship(ai_settings,screen)
- run_game()
③模块的搜索顺序
Python的解释器在导入模块时,会:
1.搜索当前目录指定模块名的文件,如果有就直接导入
2.如果没有,再搜索系统目录
在开发时,给文件起名,不要和系统的模块文件重名
Python中每一个模块都有一个内置属性 __file__ 可以查看模块的完整路径
④原则——每一个文件都应该是可以被导入的
•一个独立的 Python 文件就是一个模块
•在导入文件时,文件中所有没有任何缩进的代码都会被执行一遍
实际开发场景:
•在实际开发中,每一个模块都是独立开发的,大多都有专人负责
•开发人员通常会在模块下方增加一些测试代码
◦仅在模块内使用,而被导入到其他文件中不需要执行
__name__ 属性
__name__ 属性可以做到,测试模块的代码只在测试情况下被运行,而在被导入时不会被执行!
•__name__ 是 Python 的一个内置属性,记录着一个 字符串
•如果 是被其他文件导入的,__name__ 就是 模块名
•如果 是当前执行的程序 __name__ 是 __main__
if __name__ == '__main__'表示:当模块被直接运行时,下面的代码块将被允许,当模块被其他程序文件调用时,下面的代码块不被运行。
- if __name__ == '__main__':
-
- #测试代码
•包是一个包含多个模块的特殊目录
•目录下有一个特殊的文件__init__.py
•包名的命名方式和变量名一致,小写字母 +“ _”
使用import包名可以一次性导入包中所有的模块
__init__.py:要在外界使用包中的模块,需要在__init__.py中指定对外界提供的模块列表。
当用 import 导入该包时,会执行 __init__.py 里面的代码。可以在__init__.py定义__all__ 变量,定义需要导入的模块。比如:
__all__ = ['subpackage_1', 'subpackage_2']
- #导入pygame游戏安装包
- import pygame
- screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
- pygame.display.set_caption("Alien Invasion")
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。