python刚刚入门,总结一下上网课 (小甲鱼) 时学到的python基本语法。
有一点c的基础,主要总结和c不太一样的地方。
+++++++++++++++++
声明📢 :
文章是我个人的笔记,写在这里和大家分享。里面的内容都是看小甲鱼python网课时自己总结的一些知识点。
有些内容,可能是我自己百度了之后,看了别人的文章之后的笔记。具体的网址都在文章中标记出来了。
++++++++++++++++
感谢支持。如果有什么建议,或者是文章内容有什么错误/问题,麻烦指出来,会及时改进的
+++++++++++++++++
语法入门结束之后,开始刷面试题了。如果大佬们有什么,关于语法入门之后怎么练习的建议,麻烦评论区指点一下。谢谢!
文章里面可能有很多英文,主要是因为一长串中/英文读起来容易找不到重点,将关键字用英语标出来, 对我个人读起来有些帮助
文章有些地方,不是顺序来写的。如果见到一些不认识的函数或者用法,可以检索一下文章,找到他们的定义
目录
注意项
- 不需要semicolon ;
- indentation缩进 代替{ }
- 变量不需要declare type,可以直接赋值。
- 不需要格式符号%d,%lf
- “” 或者’ '都可以用来标注字符串
- 每次print执行完了之后,都会默认换行。可以更改这一设定👇:
print("hello world", end='')
print('hola')
#end=规定每次打印结束以什么来结尾
- 一个print函数打印多个字符串
print(a, b, c)
#默认字符串用空格隔开
print("hello" * 3)
#打印“”里面的内容3次
结果:hellohellohello
print("hello" + "world")
结果:helloworld
打印特殊符号
转义符号
当要打印字符串里面的 ', " ,\n, \t, 或者位于句末的\时
print("lower\\")
结果:lower\
加上r
这个语句会自动给字符串中所有的 \ (不包括句末的\) 转义
string = r'\n\t'
print(string)
\n\t
打印多行的字符串
使用三个“ 或者 ‘
print('''hello
world''')
#打印结果会自动换行
hello
world
if else
不要忘记冒号和indentation
if a == 1:
print(' a == 1')
elif a == 2:
print(' a == 2')
else:
pass #什么都不写的时候用
三元操作
string = a if a < b else b
或者
if a < b:
string = a
else:
string = b
else其他用法
- 和while, for一起用
写在else里面的code,只在循环全部结束之后才会执行。也就是,如果中间break, 则不执行。
for i in list1:
if i == 6:
break
print(i)
else:
print('There is no 6 in the list')
如果 list1 = range(0, 10, 4)
0
4
8
There is no 6 in the list
如果list1 = range(0, 10, 3)
0
3
- 同理,else可以和try语句一起用。如果try语句中没有出现exception,则执行else里面的内容
try:
raise OSError
except OSError:
print('error')
else:
print('success')
while
不支持do while
a = 1
while a < 2:
print(a)
a += 1
#⚠️python不支持++,--
1
for
主要适用于list或者tuple
⚠️这里的i和j不是一个counter,而是这个list里面的一个元素element
for i in list1:
for j in i:
print(j)
运算符
逻辑运算符
&& and
|| or
! not
算数运算符
/ 为数学意义上的除法,整数之间相除可以得到小数
// 为floor除法,即使operands是小数,结果依然为整数
** 幂
- 比左侧的单目运算符高,比右侧的低
-3 ** 2 == -9
3 ** -2 == 0.11111
比较符
支持 3<4<5,相当于 3<4 and 4<5
类Class
命名规则:ClassName
类包含一系列的变量(属性attribute)和函数(方法)
避免变量与函数重名,否则变量会覆盖函数。
class Car():#如果在定义的时候,把其他的类当作参数放进来,那么可以继承这个类的所有变量或者函数
#变量
name = 'carro'
color = 'red'
#函数
def calculate_speed(self, distance, time):
speed = distance / time
print('%s is travelling at %f m/s' % (self.name, speed))
#⚠️ 除了在定义变量的部分,使用变量的话,都需要明确是哪一个对象(e.g. self.name而不是name)
类理解为一个模版,对象object(或者实例)则是这个模版刻出来的一个物品。类在定义的时候,是类。定义结束,是类对象。
我们可以创建一个对象:
car1 = Car()
print(car1.name)
print(car1.calculate_speed(30, 10))
carro
3.0
解释一下self:
当通过实例对象调用函数的时候,会把实例当作参数传入到函数里面。这是python 的绑定机制,self就是用来接收这个对象的 (个人理解,如果有错误,麻烦指出来,谢谢! )
继承
使用继承的方法,在前面有写过。
如果子类在定义的过程中,定义了和父类同名的变量/函数,会覆盖父类,但是并不会影响父类。
如果,想要保留父类同名的变量/函数,可以使用super
super(). 函数名()
init的定义,见魔法方法
class Parent:
def __init__(self):
print("I'm the parent")
class Child(Parent):
def __init__(self):
super().__init__() #在重新定义的时候,保留一下父类的内容
print("I'm the child")
parent = Parent()
print('----分界线----')
child = Child()
I'm the parent
----分界线----
I'm the parent
I'm the child
组合
在定义一个类的时候,创建另外一个类的object
class Female:
def __init__(self, input):
self.number = input
class Male(Female):
pass
class Class:
def __init__(self, inputF, inputM):
self.female = Female(inputF)
self.male = Male(inputM)
def statement(self):
print("We have %d female students & %d male students" % (self.female.number, self.male.number))
class1 = Class(25, 24)
class1.statement()
We have 25 female students & 24 male students
类vs类对象vs实例对象
对类对象进行操作,会对这个类的所有objects作出操作。如果,对类的一个object进行操作,则只对这个object生效。
(原理是,这个object自己生成了一个变量,覆盖了类里面定义的那个变量。从此之后,再更改类对象也不会影响这个object,因为已经被覆盖了)
一切皆对象
一开始看网课不是很明白,搜到了一个其他楼主的文章明白了一点。
下面总结一下我个人读完这个文章之后的理解。原文:(链接:https://blog.youkuaiyun.com/hpu120623/article/details/90745739)⬅️ 文章里面有具体的例子和流程图,推荐读!
所有所谓的数据类型(序列,字典,int,str)这些都是type这个类的对象。
那么具体的变量 (e.g. list1, dict1, 3, ‘hello’) 是相对应的数据类型的对象。
最后,type本身就是type这个类的对象。
所以,都是对象。。。
如果想要有更深刻的理解,建议可以自己平时多试试打印某个东西的type是什么。极大的可能性返回的都是<class ‘something’>.
数据类型
区分int & float
有无小数点
科学记数法
默认为float
a = 1e-12
序列sequence
序列包括了list, tuple, 等等。这些类都具有一个特点就是有序。所以被统称为序列。序列本身并不是一个类,只是一个名词。
支持的操作:
- slice
- 重复操作(*),拼接(+),关系(in, not in)
其他操作:简述可能的操作,具体的函数不介绍
- 判断序列里,是否含有另外一个序列
- 查找某一个element或者sequence,返回其index
- 查找index中存储的element
- 查找最大/小值 (前提:所有elements为同一个类型)
- 查找某个element出现的次数
index支持负数,意为倒数 (e.g. -1意思是倒数第一)
列表list
- 空列表:[]
- 可以更改,添加,删除element
创建一个列表:
list1 = [1, 'hello', 2.0]
#可以存放不同类型的元素
或者:
list1 = list([1, 'hello', 2.0])
#注意list()里面可传入任何iterrable (e.g. tuple,set)
添加element
append(element)
list1.append(3)
#追加一个element,一次只能添加一个
extend(list)
list1.extend([0, 2.4])
#输入的list会与当前的list合成一个list
#或者
list2 = list1 + list2
insert(index, element)
list1.insert(0, 'hello')
#将一个element放到指定的index
删除element
remove(element)
list1.remove(0)
#删除输入的element
del list1[2]
del list1
#删除某一个element或者整个list
pop (index)
list1.pop(3)
#删除在这个index的element,并返回这个element
#默认为最后一个element
切片slice
[start : stop : step]
⚠️不包括stop。[start, stop)
list1[1:3]
#截取从index1到3(不包含3)的elements
#第一个参数默认为0,第二个为最后的index, 第三个为1
list2 = list1[:]
#copy整个list, 更改list1并不会影响list2, vice versa
list2 = list1[1:9:2]
#step为2
比较大小
list1 == list2
#只有当所有element相同时为true
list1 < list2
#比较第一个不相同的element
检查是否存有一个element
if 'hello' in list2:
print('yes')
if 'hello' not in lsit2:
print('no')
某个element出现次数
count ( element )
list2.count('hello')
某个element第一次出现index
index ( element, start index, stop index )
list2.index('hello', 3, 7)
#返回这个element在[3, 7)内第一次出现的index
#如果没有出现,会出现valueError
倒序
list1.reverse()
排序
list1.sort()
#默认从小到大排序,不同参数排序不同
推导式
[element + 表达式]
list1 = [i for i in range(0, 10) if i%2 == 0]
[0, 2, 4, 6, 8]
生成器对象可以直接做某些函数的参数。
range
range (start, stop, step)
⚠️不包括stop
默认第一个参数为0,第三个为1
x = range(0, 10, 3)
print(x)
print(type(x))
range(0, 10, 3)
<class 'range'>
可以理解为一个整数list。可以将它转换成list,也可以直接在for循环中用
list1 = list(range(0, 10, 3))
print(type(list1))
print(list1)
<class 'list'>
[0, 3, 6, 9]
元组tuple
和list相似,但是不能改变
- 空元组 ()
- ⚠️创建元组的标志为逗号,而不是()
tuple1 = (2, 3, 4)
tuple2 = (2,) #必须要加逗号,否则tuple2会被认为是整数
tuple3 = tuple1 * 3
tuple4 = tuple1[:2] + ('hello',) + tuple3[:]
tuple5 = tuple([1, 2, 3])
#可以传入任何iterrabLe
字符串
- python没有字符,只有字符串
- 不可以通过index直接修改element (类似元组,是不可以改变的),可以使用slice修改
str1 = 'hello!world'
#或者
str1 = str('hello!world')
str1 = str1[:5] + ' ' + str1[6:]
print(str1)
hello world
字符串操作
下面主要总结可以做什么,不介绍函数
⚠️涉及查找的函数,支持从左或从右查找
- 改变大小写
- 居中,左对齐,右对齐 字符串
- 判断字符串是否以sub string结束/开始
- 判断字符串里有无数字,字母,大小写,title(首字母大写)
- 用指定的字符串,分隔当前字符串
- 去掉/替换 字符串中指定的sub string
格式化字符串:按照规定的格式输出字符串
format
用{}来表示需要replacement的地方
- 未知参数 non-keyword
statement = "{0} has {1} files"
statement = statement.format("John", 10)
#⚠️format只是返回一个更新之后的字符串,并不是彻底更改statement
John has 10 files
- 关键字参数 keyword
statement = "{a} has {b} files"
statement = statement.format(a = "John", b = 10)
John has 10 files
可以混合使用未知&关键字参数,但是未知必须在关键字之前使用
如果想要打印 { }
a = '{{0.1}} is a {0}'.format('union')
print(a)
#{}用来转义{},相当于上面的转义符号,所以{0.1}会被当作普通character打印
{0.1} is a union
格式化符号
%c
a = '%c %c %c' % (97, 99, 100) #⚠️一定要加括号
print(a)
a c d
%s, %d
str1 = '%s += %d' % ('hello world!', 100)
print(str1)
hello world! += 100
%f, %e (%E), %g(%G)
%g 自动判断是使用小数还是科学记数法, 不支持指定精确到小数点后几位
#10.1: 10表示输出的结果至少为10位,如果不够空格来凑,1表示小数点后1位
str1 = '%0.1f == %10.1e == %g' % (1000000, 1000000, 1000000)
print(str1)
1000000.0 == 1.0e+06 == 1e+06
其他: 左右对齐,正数前面加+, 不同进制,规定输出width(可选用空格还是0来填充),百分比
映射:字典dict
- 与上面的序列不同,dict是属于映射类型的。
- 通过输入key,来获取,或者重新赋值,相对应的某个value。这种key和value相对应的关系就是映射。
- 可以使用in 和not in,但是⚠️查找的是key,不是value。
- items没有指定的顺序
- 标志:冒号:, 如果没有冒号,则被默认为集合(下面)
dict1 = {'apple' : '🍎', 'banana' : '🍌', a : b, 1 : 2}
#或者
dict1 = dict( ( ('apple', '🍎'), ('banana', '🍌'), (a, b), (1 , 2) ) )
print(dict1['apple'])
print(dict1[a])
print(dict1[1])
🍎
b
2
dict1['apple'] = 苹果 #重新赋值
#如果apple这个key不存在,python会自动创建一个item
字典操作
下面列举的,使用的时候需要明确是对哪一个dict操作:e.g. dict1.fromkeys()
- fromkeys(),创建一个新的dict。可以用在如果在这个字典里所有keys都对应同样的value时。
- keys(), 返回dict里面的所有keys。一般用在for里面。类似的还有values(), items()
- get(),可以自定义,当access一个不存在的key时,返回的值。
- clear(),清空一个字典。彻底清除这一个指针(e.g. dict1)所指向的数据。
- pop(key),返回,输入的key所对应的value,并且删除整个item
- popitem(), 随机删除并返回一个item
- setdefault(key, value) 在这个字典里添加一个item
- update(dict),用一个字典来更新另外一个。(只更新两个字典中都有的key,所对应的value)
推导式:
{key : value+表达式}
dict1 = {i:i % 2 == 0 for i in range(0, 10)}
{0: True, 1: False, 2: True, 3: False, 4: True, 5: False, 6: True, 7: False, 8: True, 9: False}
集合set
- 无序
- 不支持index索引 e.g.不可以写 set1[2]
- 支持in, not in
- 可以删除/添加element
set1 = {1, 3, 4, 2, 5, 4} #没有映射关系
#或者
set1 = set([1, 3, 4, 2, 5, 4])
#set()可以接收list, tuple, string
print(set1)
{1, 2, 3, 4, 5}
⚠️集合里面所有的elements都是唯一的
推导式
{element + 表达式}
set1 = {i for i in [0, 0, 0, 0, 0, 1, 2]}
{0, 1, 2}
不可变集合frozenset
与set相似,但是创建的对象是不可以被更改的set
BIF/类
下面要介绍的有一些是BIF,有一些是<class ‘builtin_function_or_method’>的对象,有一些是类。不具体的进行区分。
assert
assert condition
当condition结果为true时,程序正常运行。如果false,程序自动退出,显示assertion error
可以当作"break point“使用
assert a = 0
input
返回用户输入的字符串 = input (输出的字符串)
a = int(input("Please enter a number"))
len
返回一个序列的长度(elements的数量)
max , min
返回一个序列中的最大/小值
⚠️elements必须为同一个type
sum
⚠️elements必须为同一个type
返回所有elements的总和
enumerate
其实例是将列表里的elements和其index组成一个个元组。可以将这个实例转化称sequence
zip
其实例将几个list合成一个。可以转换称sequence
filter
filter (function, sequence)
其实例是一个sequence中所有, 可以让某一个函数返回True的, elements。
如果不输入函数,其实例为所有为True的elements。可以转换为sequence
list1 = list(filter(lambda x: x % 2, range(0, 10)))
[1, 3, 5, 7, 9]
map
map (function, sequence)
其实例为所有elements传入某个函数后所得的结果
可以转换为sequence
list1 = list(map(lambda x: x + 1, range(-2, 3)))
[-1, 0, 1, 2, 3]
类相关
issubclass
返回bool = issubclass(class, classinfo)
classinfo也是输入一个类
判断class是不是classinfo的子类
⚠️
- object是所有类的父类,也就是如果classinfo输入的是object,永远返回True
- classinfo可以输入元组,但是如果任何一个element是class的父类,都会返回True
- 一个类是他自己的父类
isinstance
返回bool = isinstance(object, classinfo)
判断object是不是classinfo的实例。
⚠️
- classinfo可以输入元组,但是如果object是任何一个element的实例,都会返回True
- 如果A类是B类的子类,那么A类的实例,也是B类的实例。
hasattr
返回bool = hasattr(object, name(字符串))
判断这个实例里面有没有定义输入的变量/属性
getattr
返回name的值 = getattr(object, name[, default(字符串)])
返回这个实例中name这个变量的值
如果输入的name不存在,可以通过输入default的方法,来自定义程序返回的报错内容。
setattr
setattr(object, name, value)
给name这个变量赋值,如果name不存在,则创建一个。
delattr
delattr(object, name)
删除name这个变量,如果name不存在,则报错attribute error。
property
property(获取属性的方法,设置属性的方法,删除属性的方法)
属性=变量,方法=函数
使用property,可以直接对其实例进行以上的操作(获取,设置,改变)。不太好解释,看例子👇
class Name:
name = 'ch'
def set_name(self, name):
self.name = name
def get_name(self):
return self.name
def del_name(self):
del self.name
n = property(get_name, set_name, del_name)
如果上面的代码里,没有写最后一句(i.e.调用property)。想要设置,获取,删除需要:
name1 = Name()
#获取属性
print(name1.name)
#OR
print(name1.get_name())
#设置属性
name1.set_name('lol')
#OR
name1.name = 'lol'
#删除
del name1.name
#OR
name1.del_name()
如果调用了property:更简便
#获取
print(name1.n)
#设置属性
name1.n = 'lol'
#删除
del name1.n
魔法方法
- 可以自己定义
- 不需要手动调用,会在特殊的情况或者使用某种特殊的运算符时自动被调用
- 主要是用来给complier调用的
__ init __(self)
方法名与下划线之间没有空格。
- 当创建一个object 的时候,这个函数会自动被调用。
- 可以自己定义init函数并且添加parameters,但是,在创建object的时候,要把init函数的所有parameters都输入进去
class Car():
def __init__(self, name):
self.name = name
def calculate_speed(self, distance, time):
speed = distance / time
print('%s is travelling at %f m/s' % (self.name, speed))
car1 = Car('carro') #传入name
car1.calculate_speed(30, 10)
carro is travelling at 3.000000 m/s
可以对比之前的例子,来看一下不同的地方。
__ new __ (cls)
- 实例化过程中第一个被调用的方法。本身是进行实例化的方法。这个函数返回一个实例。
- cls相当于其他函数中的self。self指的是一个实例,cls是一个类。因为这个函数/方法就是为了创建这个类的实例,所以用cls不用self,因为self不存在。可以添加其他的函数,但是必须在创建实例的时候,传入。
什么时候需要改写?
大部分时间不需要改写。如果创建了一个类,并且这个类继承了不可变的类(e.g. tuple,str,int)。如果想要对创建的实例,在创建的时候就作出改变(i.e. 不同于不可变的类的地方),那么就需要通过改写new来实现。
⚠️其他可变的类不可以通过改写new来改变返回的实例。
例如,如果创建了一个类,这个类继承了元组tuple这个类,但是和tuple()的不同之处在于,这个类的所有实例都会在最后加上一个’c’
class AppendElement(tuple):#继承tuple
def __new__(cls, input):
input = input + ['c']
return tuple.__new__(cls, input)
#tuple默认的__new__会把一个iterrable的参数转化为元组。
#这里,对传进来的参数先操作,然后传给tuple,让tuple将参数变为元组。
tuple1 = AppendElement([2, 3, 4])
print(tuple1)
tuple2 = tuple([2, 3, 4])
print(tuple2)
(2, 3, 4, 'c')
(2, 3, 4)
__del __(self)
- 垃圾回收机制:
⚠️和del不一样(del删除变量/标签),也不是每次调用del都会调用__del__。当所有标签被删除时,系统就会执行这个方法,回收该内容。
class C:
def __del__(self):
print('调用__del__')
c = C()
c1 = c
c2 = c
del c2
print('---')
del c1
print('===')
del c
---
===
调用__del__
__ getattr _(self, name)
- 当用户访问一个在这个类中不存在的属性/变量是被调用
__ getattribute _(self, name)
- 当用户访问这个类的属性时被调用
__ setattr _(self, name, value)
- 当用户设置这个类的一个属性时被调用
__ delattr _(self, name, value)
- 当这个类的一个属性被删除时被调用
其他
这些就不一一列举了,感兴趣的可以自己搜一下,已经有很多人总结过了。
- 算数运算符:add, sub, floordiv, etc.
- 反运算:当第一个参数不支持某种算数操作时,使用第二个参数的反运算。radd, rsub, etc
- 增量赋值:iadd (+=), isub (-=)
- 单元操作符:neg (-负号), pos (+正号)
描述符
描述符是一种特殊的类,其 实例object可以被赋值给另外一个类(为了方便下面的文章,简称B类)的变量。然后通过对这个变量操作,就可以访问,设置,删除B类中的某个属性。
在上一个section中的property就是一个描述符。
什么样的类是描述符?
这个类必须实现/定义了下面三个方法中至少一个:
- __ get __(self, instance, owner)
通过返回属性来访问属性 - __ set __ (self, instance,
value)
给属性赋值 - __ delete __ (self, instance)
删除属性
self需要传入:描述符的对象
instance需要传入:B类的对象
owner需要传入:B类
迭代
可迭代的对象 iterable
一个实现了__ iter__魔法方法(下面会介绍)的对象
也就是说,这个对象的类必须定义了__ iter__这个魔法方法。
迭代器 iterator
迭代器一定是可迭代对象,但是可迭代对象不全是迭代器。
因为,迭代器是一个实现了__ iter__()和__ next__() 两个魔法方法的对象。
介绍两个BIF和魔法方法:
返回迭代器 = iter(iterable)
这个BIF会调用输入的iterable对象的__ iter__()方法。
__ iter__(self)
返回一个迭代器
如果,该类 实现了__ iter__和__ next__两个魔法方法,__ iter__()可以直接返回self,因为其对象本身就是一个iterator
返回下一个元素 = next(迭代器)
调用输入的iterable对象的__ next__(self)这个魔法方法
__ next__(self)
return下一个元素
如果没有元素可以输出了(i.e. 已经输出了最后的元素),raise StopIteration异常。
👇 建立一个类,这个类的对象是一个Fibonacci斐波拉兹序列。并且利用这两个BIF “实现” for循环:
class Fibonnacci:
a = 0
b = 1
i = 0
def __iter__(self):
return self
def __next__(self):
self.i += 1
if(self.i > 10):
raise StopIteration
else:
self.a, self.b = self.b, self.a + self.b
return self.a
Fib1 = Fibonnacci()
Fib1Iter = iter(Fib1)
try:
while(1):
print(next(Fib1Iter))
except StopIteration:
pass
1
1
2
3
5
8
13
21
34
55
函数
命名规则:function_name,parameter_name
def is_even(number):
if number % 2 == 0:
return True
else:
return False
局部,全局变量
⚠️ 如果尝试在一个function里面对一个global variable重新赋值,需要明确某一个变量是global variable
def change():
global global_v #这一句一定要有,否则结果为200
global_v = 20
global_v = 200
change()
print(global_v)
20
如果没有写global:
def change():
global_v = 20 #这里python重新创建了一个local variable,并且给它赋值20
global_v = 200
change()
print(global_v)
200
函数文档
和注释一样,在调用函数的时候不会被执行,但是可以帮助理解这个函数
def sum(num1, num2):
'这是一个用来计算sum的函数‘ #👈 函数文档
return num1 + num2
print(sum.__doc__)
'这是一个用来计算sum的函数‘
参数
关键字参数&默认参数
在没有输入参数时,使用默认参数
def sum(num1 = 3, num2 = 6): #默认参数
return num1 + num2
print(sum(num2 = 1, num1 = 2)) #关键字参数
print(sum())
3
9
收集参数
当不确定有多少个参数时
格式: def function(*参数名):
def sum(*params):
result = 0
for i in params:
result += i
print(result)
sum(1,2,55,43)
101
⚠️如果在收集参数之后,还想要添加别的参数。在调用的时候,要通过关键字参数的方法调用
print本身就有一个收集参数
内嵌函数 embedded function
内部函数可以调用外部函数内的variables,但是不可以重新赋值,除非使用"nonlocal"
def power(x):
def helper():
nonlocal x
x *= x
return x
return helper() #这里是先调用helper,然后将helper返回的值返回;
#如果写return helper, 返回的将是一个function
print(power(5))
25
def multiply(num1):
def helper(num2):
return num1 * num2
return helper
#这里return一个函数,因为multiply里面并没有num2,所以无法调用helper,并返回helper的返回值
print(multiply(2)(3))
6
lambda表达式
简化函数代码
def add(x, y):
return x + y
返回函数 = lambda parameters : return的expression
add = lambda x, y: x+y
生成器 Generator
个人理解:也是一种迭代器
和迭代器一样可以被next调用,然后返回下一个返回值。
一个定义中含有yield的函数,就会返回一个生成器。
这个函数,在执行到yield(类似return)时,会返回yield后面的值,保存函数当前运行的位置。在下一次被调用的时候,会从上一次结束的位置继续运行,直到遇到下一个yield。
利用生成器实现一个斐波拉契序列,并将其一个个输出。
def Fibonnacci():
a = 0
b = 1
while 1:
a, b = b, a +b
yield a
FibGene = Fibonnacci() #生成器
for each in FibGene: #each是next(FibGene)的返回结果
if each < 100:
print(each)
else:
break
1
1
2
3
5
8
13
21
34
55
89
生成器推导式
⚠️ 不是元组推导式,而是生成器推导式。
(yield的值 + 表达式)
evenNumbers = (i for i in range(0, 20) if not(i%2))
print(evenNumbers)
for i in evenNumbers:
print(i)
<generator object <genexpr> at 0x10b78d9a8>
evenNumbers是一个生成器👆
0
2
4
6
8
10
12
14
16
18
生成器推导式可以直接作为一些函数的参数,不需要括号。
list1 = list(i for i in range(0, 20) if not(i%2))
print(list1)
maxinList1 = max(i for i in range(0, 20) if not(i%2))
print(maxinList1)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
18
文件
打开一个文件
| 模式 | 操作 |
|---|---|
| ‘w’ | 写,如果文件已经存在,删除原有内容,重新写入;文件不存在,创建一个文件 |
| ‘r’ | 读 |
| ‘x’ | 如果文件存在,返回异常 |
| ‘a’ | 如果文件不存在,写入方式创建文件。如果文件存在,追加 |
| 下面的模式可以与上面的模式组合使用(e.g. wb, rt, ab+) | |
| ‘t’ | 文本文件 |
| ‘b’ | 二进制文件 |
| ‘+’ | 读写 |
open ('文件名‘ , ‘打开方式’)
file1 = open('test', 'w')
#打开/创建一个文件
文件操作
简单叙述可能的操作:
.close() 关闭文件
要及时关闭文件,否则写入的内容会停留在缓冲区,并没有真正的存入文件里面
.read() 按照字符个数读取,返回文件内容。默认读取全部内容。
.readline() 按照行数读取
.tell() 返回文件指针的位置 in bytes!
.seek ()移动文件指针
.list() 可以直接将文件的内容变成一个list
⚠️,在for里面,甚至可以直接将文件当作一个sequence使用:
#假设有一个文本文件file1,已经被打开
for line in file1:
print(line)
.write() 写入字符串
.writeline() 写入字符串sequence
⚠️ 从文件中写入,读取的数据都是字符串。如果要写入/读取的数据类型不是字符串,可以通过int, float等来转换,或者如果数据类型不容易转换的话,可以使用pickle模块(见模块)。
with语句
使用with语句,就不需要自己手动来关闭文件。
with open('file name', '打开方式') as 变量名:
执行文件操作
模块
-
模块 == 写的程序。
-
使用模块可以将不同的程序接在一起 (import),但是更简洁。
-
可以将一些数据(列表,字典),函数, 等保存到一个单独的文件/模块里,以后调用。
-
模块可以被其他程序import,但要确保这个模块的路径,在sys.path这个列表里面。
import sys
sys.path #这是一个列表,这个列表里面包含了一系列的文件。当import的时候,系统会到这些文件里面里寻找某个模块,如果没有找到,报错。
- 如果要被import的模块的路径,不在这个列表里。我们可以通过append的方法,将该路径添加进去。
⚠️, 使用\的时候要注意转义。 - 通过import模块,可以调用里面的程序。
import random
random_num = random.randint(0, 10)
#或者
import random as r
random_num = r.randint(0, 10)
from random import * #执行这个操作,可以直接使用里面的所有变量/函数,不需要加上random.randint,可以直接使用randint
from random import randint #可以直接使用randint
__ name__
如果在正在编写的程序中,调用__ name__,会打印’__ main__’
如果是调用一个模块中的__ name__ (e.g. moduleName.__ name__)则会打印模块名。
用处:
在一些情况下,模块中调用(不是定义)了一些函数。那么,在import这个模块的时候,这些函数也会自动被调用。
通过if __ name__ == ‘__ main__’,就可以只在run该文件的时候,调用这些函数。
OS 操作系统
使用这个模块,可以进行重命名文件,删除创建文件及目录等操作
pickle
方便不是字符串的数据,以二进制的方式,读取/写入到文件。
写入数据
import pickle
student_file = open('student.pkl', 'wb')
#⚠️以二进制的方式打开,文件后缀写成pkl方便理解
pickle.dump(list1, student_file)
student_file.close()
读取数据
import pickle
student_file = open('student.pkl', 'rb')
list2 = pickle.load(student_file)
student_file.close()
包package
意义:
- 模块通过import可以手动导入一个个的文件/模块。包则可以导入一个个的文件夹
- 更为有序。可以通过不同类型,将模块分类,组织在不同的文件夹下。
步骤:
- 创建文件夹。放入想要存放的模块。可以在这个文件夹下,创建子文件夹。
- 在这个文件夹里面,创建一个__ init__.py文件。这个文件可以是空的,但是必须从在
⚠️ 和模块一样,要确保包的路径在sys.path这个列表里面。
导入方法:
#1. 导入整个包
import package1
#2. 导入某个特殊的文件(子文件夹的文件)
#package1里面的package2中的test这个文件
import package1.package2.test
并且支持在模块中介绍的其他导入方法。
异常exception
命名规则:ExceptionName
程序可能会出现很多种异常 (e.g. ValueError, OSError),针对异常作出相应的反应,就会用到try语句
try语句
⚠️ 如果出现了指定的异常,不会显示原有的traceback语句,而是只会执行except的代码
try:
要执行的代码
except 指定的异常 [as 变量]: #这个变量用来存放出错的具体原因
如果出现指定的异常,需要执行的代码
[finally:
不管出不出现异常,都必须执行的代码。
(一旦出现异常,程序会自动调到对应的except语句中,try里面的一些代码可能不会被执行)
]
try:
with open('test.txt', 'r') as file1:
str1 = file1.read(5)
except OSError as reason:
print('文件出错,具体原因为:' + str(reason))
finally:
print('exiting...')
自己创造一个异常:
raise exception [( ‘注释’ ) ]
raise OSError('要读取的文件不存在')
2418



被折叠的 条评论
为什么被折叠?



