一.基础语法
1.基本数据类型
- 整数
a = 10
print(tyep(a))
python 的 int 类型变量,表示的数据范围没有上限
- 浮点数
a = 0.5
print(type(a))
只有 float 类型,没有 double,占8个字节
- 字符串
- 布尔类型
True
False
- …
2.算术运算符
有:+ - * / % ** //
- **
求乘方
print(4**2) # 8
print(4**0.5) # 2
- //
取整除法(地板除),整数除以整数,还是整数,但舍弃了小数部分,向下取整
print(7//2) # 3.5 -> 3
print(-7//2) # -3.5 -> -4
3.关系运算符
有: < <= > >= == !=
字符串判断大小
使用 == 即可比较字符串内容是否相同。
如果使用大于小于来比较,规则是字典序(按照字母顺序,越前越小)
4.逻辑运算符
像and or not 这一系列的运算符称为 逻辑运算符
- and 相当于Java中的 &&
- or 相当于 java 中的 ||
- not 相当于 Java中的 !
5.赋值运算符
= 赋值
a = b = 10
a,b = 10,20 # a = 10
# b=20
两数互换:
a = 10
b = 20
a,b = b,a
print(a) # 20
print(b) # 10
6.复合赋值运算符
复合赋值运算符. 例如 *+= -= = /= %=
7.空语句 pass
a = 1
if a == 1:
pass
print("pass")
else:
print("ss")
# 输出 pass
pass
表示 空语句, 并不会对程序的执行有任何影响, 只是占个位置, 保持 Python 语法格式符合要求
二.函数
1.语法格式
def 函数名(形参列表):
函数体
return 返回值
2.使用函数
例: 求 n~m 之间的和
def listSum(n,m):
sum = 0
for i in range(n,m+1):
sum += i
return sum
print(listSum(1,3)) # 6
3.返回多个值
除了可以返回单个值之外,还可以返回多个值
def reTuple():
a = 1
b = 2
return a,b
print(reTuple()) # (1, 2)
print(type(reTuple())) # <class 'tuple'>
可以看到,返回的其实是一个 元组 tuple
什么是元组呢,元组其实就是一个有序列表,一旦初始化后不可变
a,b = reTuple() # 等同于 (a,b) = reTuple()
print(a) # 1
print(b) # 2
在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便
4.函数的默认值(默认参数)
def add(x, y, debug=False):
if debug:
print(f'调试信息: x={x}, y={y}')
return x + y
print(add(10, 20))
print(add(10, 20, True))
如果第三个参数不传递值,就会使用默认值。需要注意的是,函数的默认值必须在后边,否则会报错。
而且如果有多个默认参数,在调用的时候,默认参数可以不调用,但如果参数位置不对应,是需要指定调用哪个参数的。
def enroll(name,age,gender='女',city='bejing'):
print('name:',name)
print('age:',age)
print('gender:',gender)
print('city:',city)
enroll('cy',18,'男')
enroll('xb',22,city='guizhou')
# name: cy
# age: 18
# gender: 男
# city: bejing
# name: xb
# age: 22
# gender: 女
# city: guizhou
需要注意的是,定义默认参数时,默认参数必须指向不可变对象
todo
5.关键字参数
如果在传入参数的时候,想不按照顺序来要怎么做呢?
def test(x, y):
print(f'x = {x}')
print(f'y = {y}')
test(x=10, y=20)
test(y=100, x=200)
输出:
x = 10
y = 20
x = 200
y = 100
其实就是在传入参数的时候对参数名进行赋值,类似于这样的操作
6.可变参数
可变参数也就是说参数的个数是可变的
def calc(*number):
sum = 0
for i in number:
sum = sum + i
return sum
print(calc(1, 3)) # 4
print(calc(1,3,5)) # 9
print(calc(1,3,5,7)) # 16
# 如果想传入列表或者tuple
alist = [1,3,5,7]
mytTuple = (1,2,3,4)
print(calc(*alist)) # 16
print(calc(*mytTuple)) # 10
可以看到传入的参数是可变的。为什么参数前面要带*呢?
如果不带*,而是
def calc(number):
那传递的参数就只能是一个了。
而在传递 list 或 tuple 的时候,对应的引用为什么也要加 *呢?
如果不加*,则会报错,或者这样调用:
print(calc(alist[0],alist[1],alist[2]),alist[3])
7.命名关键字参数
对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。如果想知道传入什么,可以进行检查。
例如:调用一下函数时,检查是否含有 city
和 job
参数
def person(name,age,**kw):
if 'city' in kw:
print('传递过来的参数含有 city:',kw['city'])
if 'job' in kw:
print('传递过来的参数含有 job:',kw['job'])
person('cy',21,city = 'shanghai',job='测试开发')
# 传递过来的参数含有 city: shanghai
# 传递过来的参数含有 job: 测试开发
在调用的时候仍然可以出啊书不受限制的关键字参数,而且可以传入任意的关键字参数,不过必须制定关键字昵称。可以理解为传入的是一个键值对。kw
将获得一份 dict
和关键字参数不同,命名关键字参数 **kw
需要一个特殊分隔符*
,*
后面的参数被视为命名关键字参数。
三.列表和元组
1.列表
1)创建列表
alist = [1,'python',1.11]
print(alist) # [1, 'python', 1.11]
print(type(alist)) # <class 'list'>
2)通过下标访问
for i in range(len(alist)):
print(alist[i])
输出:
1
python
1.11
直接赋值可以修改
下标取负数,则是指从右往左取值
alist[-2] # python
range(1,11)
相当于list [1,2,3,4,5,6,7,8,9,10]
for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
3)切片操作
取出子列表
alist = [1,2,3,4]
print(alist[1:2]) # [2] 左闭右开
print(alist[1:]) # [2, 3, 4]
print(alist[:3]) # [1, 2, 3]
print(alist[:]) # [1, 2, 3, 4]
4)新增元素
有两种方式:
alist = [1,'python',1.11]
alist.append(2222)
print(alist) # [1, 'python', 1.11, 2222]
alist.insert(1,'newstr')
print(alist) # [1, 'newstr', 'python', 1.11, 2222]
append()
就相当于 List.add()
,即尾增。
insert()
则是指定下标插入一个元素
5)查找元素
- 使用
in
操作符,判定元素是否在该列表中
例如要查找 1 是否在这个列表中:
print(1 in alist) # True
print(2 in alist) # False
- 使用
index
方法,查找元素在列表中的对应下标
alist = [11,33,22,44]
print(alist.index(22)) # 2
print(alist.index(66)) # 元素不存在,报错
6)删除元素
7)连接链表
2.元组
元组操作和列表类似,但初始化后是无法修改的
atuple = ()
atuple = tuple()
元组比起列表,有什么优势呢?
- 元组初始化后无法修改,可以保证数据的安全性
- 可 hash 的对象,可哈希的对象的前提就是不可变。元组可以作为字典的键,但列表不行。
四.字典
1.创建字典
字典是一种存储键值对的结构
a = {"id":1,'name':'zhangsan'}
print(a) # {'id': 1, 'name': 'zhangsan'}
2.获取 value
查看 key 值是否存在:
print('id' in a) # True
print('score' in a) # False
通过 key 获取 value:
print(a['id']) # 1
print(a['name']) # zhangsan
print(a['score']) # key 值不存在,抛异常
3.操作字典元素
新增/修改元素:
print(a)
a['score'] = 88 # 如果该 key 值不存在,则新增该键值对
print(a)
a['score'] = 90 # 如果存在,则修改对应的 value 值
print(a)
#{'id': 1, 'name': 'zhangsan'}
#{'id': 1, 'name': 'zhangsan', 'score': 88}
#{'id': 1, 'name': 'zhangsan', 'score': 90}
删除元素:
a.pop('score')
print(a) # {'id': 1, 'name': 'zhangsan'}
4.遍历字典
for 循环遍历:
可以获取 key 值,然后通过 key 值来获取 value 值
for key in a:
print(key,a[key])
# id 1
# name zhangsan
遍历:
# 迭代 key
print(a.keys())
# dict_keys(['id', 'name'])
for key in a.keys():
print('key:',k)
# 迭代 value
print(a.values())
# dict_values([1, 'zhangsan'])
for value in a.values():
print('value:',value)
# 同时迭代 key 和 value
print(a.items())
# dict_items([('id', 1), ('name', 'zhangsan')])
for k,v in a.items():
print(f'{k}:{v}')
5.合法的 key 类型
可哈希的 key 都是合法的,也就是可以计算出一个哈希值。
print(hash(0))
print(hash(3.14))
print(hash('hello'))
print(hash(True))
print(hash(())) # ( ) 是一个空的元组
0
322818021289917443
-1751379255290128896
1
5740354900026072187
而像字典dict和列表list 都是无法计算出哈希值的,也就是不可哈希类型,不可作为 key 值
五.文件
1.什么是文件?
在我们运行一个py程序的时候,变量会把当前的数据保存在内存中,如果程序重启,内存中的数据就会丢失。想要使数据持久化存储,就可以将数据存储到硬盘中,也就是保存在文件中。
2.文件的路径
文件的路径描述的是一个文件所在的位置,通过这个路径就可以定位到这个文件。以 windows为例子,一个文件的路径一般是[盘符] [目录] [文件]
E:\图片\喜欢\QQ图片20221128003530.jpg
像上边的路径:
E:
表示的是盘符,不分大小写\
表示一级目录,当前图片文件是放在 "E 盘"下的"图片"目录的"喜欢"目录底下
1)绝对路径
像E:\图片\喜欢\QQ图片20221128003530.jpg
就是一个绝对路径,把详细的路径信息描述了出来
2)相对路径
用一个基准目录作为参照点,用.
表示这个基准目录。
例如,我们当前创建一个py项目,那么我们在项目中是以这个项目的根目录作为基准目录的:
当前的基准目录为:E:\python\api_autotest
然后我们可以用相对路径.cases\customer\test_customer.py
来表示 test_customer.py
的具体位置。如果是绝对路径则是E:\python\api_autotest\cases\customer\test_customer.py
3.操作文件
E:\test.txt:
这是一个文本文件
1)打开文件
f = open('文件路径','r')
- 第一个参数是文件的路径
- 第二个是打开文件的方式。
r
表示以只读的方式打开,w
表示按照写的方式打开,a
表示按照追加写的方式打开。 - 返回的是一个文件对象,后续是通过操作这个对象,来操作文件
2)关闭文件
使用close()
来关闭打开的文件
f.close()
文件的打开需要及时的关闭,虽然python有内置的垃圾回收机制,会在文件对象被销毁的时候自动关闭文件。但为了保险起见,仍然要手动关闭,因为垃圾回收操作可能会不及时。
3)写文件
f = open('e:\\test.txt','w')
f.write('hello,world!')
f.close()
打开文件则会发现,当前的内容由"这是一个文本文件"变成了:
hello,world!
也就是写是默认覆盖写的方式
如果不想覆盖掉原来的内容,则可以使用覆盖写的方式:
f = open('e:\\test.txt','a')
f.write('hello,world!')
f.close()
再次打开文件:
hello,world!hello,world!
4)读文件
f = open('e:\\test.txt','r')
print(f.read())
f.close()
返回的是文件所有内容。
可以传入参数,指定获取内容:
f = open('e:\\test.txt','r')
print(f.read(1)) # 读取第一个字符
f.close()
#h
读取行:
如果文件内容是多行文本:
hello world1
hello world2
hello world3
想逐行读取,可以:
f = open('e:\\test.txt','r')
for s in f:
print(f'line={s}')
f.close()
读取结果:
line=hello world1
line=hello world2
line=hello world3
注:文本文件后边默认跟着换行符"\n"
也可以使用readlines()
方法:
f = open('e:\\test.txt','r')
result = f.readlines()
print(type(result))
print(result)
f.close()
# <class 'list'>
#['hello world1\n', 'hello world2\n', 'hello world3']
返回的是一个list,每一个元素对应指每一行
4.指定字符集
计算机在表示中文的时候,会采取一定的编码方式,即”字符集“
计算机只能表示二进制数据,要想表示英文字母、汉子或者其他的文字符号等,都需要通过编码。
本质是使用数字表示
ASSCII字符编码:使用一个简单的整数就可以表示英文字母和阿拉伯数字。但无法表示汉子,常用的汉字编码方式, 主要是 GBK 和 UTF-8
要保证编码方式统一,才能正常的读取文件内容
打开txt文件,可以看到文件的编码方式:
- 如果编码是 ANSI , 则表示 GBK 编码.
- 如果编码是 UTF-8 , 则表示 UTF-8 编码.
指定字符集打开文件:
f = open('d:/test.txt', 'r', encoding='utf8')
关于字符集,参考文章:https://zhuanlan.zhihu.com/p/46216008
5.上下文管理器
虽然知道打开文件后最好要关闭,但还是容易忘记关闭。这时候就可以使用python提供的上下文管理器,来帮助我们解决这个问题。
with open('d:/test.txt', 'r', encoding='utf8') as f:
lines = f.readlines()
print(lines)
- 使用 with 语句打开文件
- 当 with 内部的代码块执行完毕,就会自动调用关闭方法
f.close()
六.面向对象编程
1.类和实例
类(Class)是抽象的模板,而实例(Instance)是根据类这个模板创建出来的“对象”。
由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__
方法,在创建实例的时候,就把name
,score
等属性绑上去:
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score!
注意到__init__
方法的第一个参数永远是self
,表示创建的实例本身,因此,在__init__
方法内部,就可以把各种属性绑定到self
,因为self
就指向创建的实例本身。
有了__init__
方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__
方法匹配的参数,但self
不需要传,Python解释器自己会把实例变量传进去
2.访问限制
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
,在Python中,实例的变量名如果以__
开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。
class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def print_score(self):
print('%s: %s' % (self.__name, self.__score))
如果外部想要访问 private 权限的字段,可以提供 get 方法,想要修改可以提供 set 方法
def get_name(self):
return self.__name
def get_score(self):
return self.__score
def set_score(self, score):
self.__score = score
def set_name(self,name):
self.__name = name
需要注意的是,在Python中,变量名类似__xxx__
的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name__
、__score__
这样的变量名。
3.继承和多态
什么是继承,子类继承父类。子类可以获得父类所有的字段和方法,同时子类也能够拥有自己的字段和方法。
所有类默认继承 object
todo
https://www.liaoxuefeng.com/wiki/1016959663602400/1017497232674368
4.获取对象信息
1)获取类型
使用 type()
方法可以获取到对象的类型
print(type(123))
print(type('123'))
print(type(123.123))
print(type(True))
# <class 'int'>
# <class 'str'>
# <class 'float'>
# <class 'bool'>
2)判断 class 的类型
使用 isinstance()
来判断 class 的类型是否一致
ininstance(class1,class2)
如果一致,返回 True。否则返回 False
isinstance()
判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上。
5.实例属性和类属性
由于Python是动态语言,根据类创建的实例可以任意绑定属性。
给实例绑定属性的方法是通过实例变量,或者通过self
变量:
class Student(object):
def __init__(self, name):
self.name = name
s = Student('Bob')
s.score = 90
但是,如果Student
类本身需要绑定一个属性呢?可以直接在class中定义属性,这种属性是类属性,归Student
类所有:
class Student(object):
name = 'Student'
当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到。来测试一下:
>>> class Student(object):
... name = 'Student'
...
>>> s = Student() # 创建实例s
>>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
Student
>>> print(Student.name) # 打印类的name属性
Student
>>> s.name = 'Michael' # 给实例绑定name属性
>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael
>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
Student
>>> del s.name # 如果删除实例的name属性
>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
Student
从上面的例子可以看出,在编写程序的时候,千万不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。
结束语: 本文只用于记录学习,参考: 廖雪峰的python教程