python基本语法整理

python刚刚入门,总结一下上网课 (小甲鱼) 时学到的python基本语法。
有一点c的基础,主要总结和c不太一样的地方。

+++++++++++++++++
声明📢 :
文章是我个人的笔记,写在这里和大家分享。里面的内容都是看小甲鱼python网课时自己总结的一些知识点。
有些内容,可能是我自己百度了之后,看了别人的文章之后的笔记。具体的网址都在文章中标记出来了。

++++++++++++++++
感谢支持。如果有什么建议,或者是文章内容有什么错误/问题,麻烦指出来,会及时改进的

+++++++++++++++++
语法入门结束之后,开始刷面试题了。如果大佬们有什么,关于语法入门之后怎么练习的建议,麻烦评论区指点一下。谢谢!

文章里面可能有很多英文,主要是因为一长串中/英文读起来容易找不到重点,将关键字用英语标出来, 对我个人读起来有些帮助

文章有些地方,不是顺序来写的。如果见到一些不认识的函数或者用法,可以检索一下文章,找到他们的定义

注意项

  • 不需要semicolon ;
  • indentation缩进 代替{ }
  • 变量不需要declare type,可以直接赋值。

print

  • 不需要格式符号%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其他用法

  1. 和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
  1. 同理,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.csdn.net/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)

其他操作:简述可能的操作,具体的函数不介绍

  1. 判断序列里,是否含有另外一个序列
  2. 查找某一个element或者sequence,返回其index
  3. 查找index中存储的element
  4. 查找最大/小值 (前提:所有elements为同一个类型)
  5. 查找某个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的地方

  1. 未知参数 non-keyword
statement = "{0} has {1} files"
statement = statement.format("John", 10)
#⚠️format只是返回一个更新之后的字符串,并不是彻底更改statement
John has 10 files
  1. 关键字参数 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)

  • 当这个类的一个属性被删除时被调用

其他
这些就不一一列举了,感兴趣的可以自己搜一下,已经有很多人总结过了。

  1. 算数运算符:add, sub, floordiv, etc.
  2. 反运算:当第一个参数不支持某种算数操作时,使用第二个参数的反运算。radd, rsub, etc
  3. 增量赋值:iadd (+=), isub (-=)
  4. 单元操作符:neg (-负号), pos (+正号)

描述符
描述符是一种特殊的类,其 实例object可以被赋值给另外一个类(为了方便下面的文章,简称B类)的变量。然后通过对这个变量操作,就可以访问,设置,删除B类中的某个属性。
在上一个section中的property就是一个描述符。

什么样的类是描述符?
这个类必须实现/定义了下面三个方法中至少一个:

  1. __ get __(self, instance, owner)
    通过返回属性来访问属性
  2. __ set __ (self, instance,
    value)
    给属性赋值
  3. __ 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

意义:

  1. 模块通过import可以手动导入一个个的文件/模块。包则可以导入一个个的文件夹
  2. 更为有序。可以通过不同类型,将模块分类,组织在不同的文件夹下。

步骤:

  1. 创建文件夹。放入想要存放的模块。可以在这个文件夹下,创建子文件夹。
  2. 在这个文件夹里面,创建一个__ 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('要读取的文件不存在')
展开阅读全文
©️2020 CSDN 皮肤主题: 1024 设计师: 上身试试 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值