Python学习笔记
1.变量和简单数据类型
python是一门动态的变成语言,我对动态的理解就是,在编程过程中,变量是是没有确定的类型的,你给变量赋值的类型决定了变量的类型。
a = 1.0
a = “hello”
a = 2
变量的命名也要满足一定的规则,这对于已经接触过编程的人来说,是个很容易理解的事情。
在python中,表示字符串可以有两种不同的方式
str1 = “hello1”
str2 = ‘hello2’
str1.title() —–> “Hello1” #使用字符串的title方法可以使它的首字母大写
str1 + str2 = hello1 hello2 # 字符串的拼接可以通过+号来进行
单引号和双引号都可以作为构建字符串。
删除字符串中的空格部分:str.rshtrip() str.lstrip() str.strip()
python中计算一个数的幂指数:2**3 = 8,这个形式和Fortran是相同的
字符串和数值是两种不同的数据形式,如果想要它们之间可以进行操作 str1 + str(num) ,可以通过函数将一个数值转换成字符串的形式后进行拼接。
在python中,通常使用#来做为注释,它后面的内容不会被作为代码。通常如果注释内容较多,可以通过‘’‘ ’‘’来进行多行注释。
2.列表简介
列表的记号是list1 = [],列表内的数据类型可以是任意的,它同样也可以再包含一个列表。python中需要注意一点,它的列表索引是从0开始的,这与Fortran还有Julia都是不同的,这两个编程语言的index是从1开始的。要使用列表中的元素,只需要通过该元素对应的索引位置即可。==python中索引是用[]来识别的,这一点和Julia相同,而Fortran则是用()来进行元素索引==。
list.append(str1) list中增加元素,追加到list尾部
list.insert(index,str1) 在list确定的位置上增加元素
del list[index] 删除list确定位置上的元素
list.pop() 删除list中最后一个元素(列表就像一个栈,可以通过一定的顺序将这些元素依次取出),该方法只是单纯的将这个元素读取出来,而不会修改list,相反del则会对list进行直接的修改
list.remove(str1) 当知道要删除的元素时,也可以直接根据元素名来删除元素。
list.sort() 可以对list中元素进行排序,它会永久的修改list
list.sorted() 临时对list进行排序,不会改变本来list中的元素顺序
list.reverse() 倒置list中的元素
len(list) 返回list中元素的数量
3.操作列表
在一般静态编程语言中,如果要遍历list中的元素,通常时通过循环list中的每一个index,在python中可以有另外的方式,list具有一个可迭代属性,我们可以直接对list进行循环
list = []
for mag in list:
print(mag)
==在python中,for循环后面的**冒号(:)**是很重要的,而且一定要有代码缩进,这样编译器才能区分到底那一部分是什么内容,再说一遍,python中的缩进是非常重要的,如果使用了错误的缩进,则有可能导致程序得到错误的结果==
range(1,5)—–>1,2,3,4 这一点在python中需要注意,它只是遍历了4个元素
list(range(1,5))—-[1,2,3,4] 将range产生的对象转变成数字列表的形式
列表解析
通常要生成一个合适的列表,需要利用循环在进行,然而列表解析是一个更简单的方法可以让你更方便的得到所需要的列表
[val**2 for val in range(1,5)] —->[1,4,9,16] 这样可以直接得到数字列表而不用再次进行转换
当想要通过index获取列表的一部分时,可以通过列表切片来达到这个目的
list[start:end] 通过确定的1:4这种形式来确定要切片的范围
==在python中要注意一个问题,我们对于list的引用时按址引用的,假设有一个list1,如果list2=list1,那么list2和list1在内存中的指向是相同的,当你修改它们中的任何一个,另外一个也都会跟着改变,因为本质上它们是同一个东西==
==如果想要解决这个问题,完成真正的赋值操作,则应该利用切片进行list2 = list1[:],通过这样list1和list2是两个不同的内存空间,修改任意一个不会影响另外的一个==
元组
通过上面的学习可以清晰的认识到,列表中的元素是可以进行修改的,那么如果想要对象的值不能进行改变,那么就需要用到元组来对数据进行存储。
元组的定义方式是通过圆括号() 来进行的。tuple1 = (val1,val2,…),元组的操作和列表基本一致,除了元组中所有的元素都不能进行修改之外,其余的包括索引,取值,引用等都是相同的。
4.字典
在python中,字典是一系列键值对,每个键都与一个值相关联。可以通过键来访问其对应的值,同样的和列表相同,字典内间是字符属性,而其值可以是任何的类型,包括是字典。
dict1 = {‘k1’:v1,‘k2’:v2,…}
字典的index需要通过字典内的键来进行,dict1[key]就可以获取键key所对应的值是多少,熟悉了list的操作的话,那么字典的操作和list是相同的。==不过和list区别的一点是,字典中的这些操作,你必须是用key来做index,而不像list中只是用数字索引来进行操作==
当对字典进行遍历的时候,可以同时获取字典中的键和值
for key,val in dict.item(): # 同时获取键和值
key….
val…
for key in dict.keys(): #单独获取字典中的键
key….
for val in dict.values(): #单独获取字典中的值
val….
当获取了字典中的键与值之后,就可以进行相关的操作了。在上面提及到,列表中的内容可以是任何的数据类型,同样的我们可以将一系列字典放到列表之中,组成我们想要的数据结构。
反过来,也可以将字典中某一个键的值设置成列表的形式。
5.用户输入和while循环
input函数可以等待用户从输入设备输入内容,读取到程序。int函数可以将读取到的数值形式的字符串转变成数值形式
a = input() # a = ‘123’
b = int(a) #b = 123
while循环通过逻辑判断该过程是否还要继续重复进行
while i1>10:
i1 += 1
使用标志
假设现在有一个函数,它的内部有一个循环,这个循环并不是每次调用函数都需要去执行,它需要在这个函数满足特定条件的时候,函数里面的这个循环才回去执行,这时候我们可以通过设定一个变量,用这个变量来决定这个循环时候要被激活,这个变量就叫做标志
active = True
while active:
。。。。。。。
如上所示,active就是一个标志,用来决定while循环是否要被执行
break可以用来直接退出循环(当有多层循环的时候,break只是退出它所在的那一层循环)
continue可以用来跳过这一次的循环。
while i1<10:
i1 +=1
if i1==5:
contionue
print(i1)
有上面的这个例子就可以说明,当i1=5的时候,循环过程并不会打印5这个值,因为这一步在循环中被挑了过去
6.函数
def function_name(parameter):
函数内容
通过def来定义函数,注意后面要有冒号(:)和代码缩进,以此来识别那些是函数的主体部分
位置实参
def function1(p1,p2):
p3 = p1 + p2
这就是位置实参的意思,通过两个形式参数来作为函数的接受变量,在位置实参的情况中,在调用函数的时候参数的位置顺序是很重要的。
关键字实参
def func1(p1,p2):
reutrn p1 + p2
print(func1(p1 = 1,p2 = 2))
关键字实参的意思就是,在使用函数的时候,你知道函数定义时每个形参的名字,可以在调用时通过参数名=变量的形式来调用函数,这个时候参数的调用顺序是可以变的。
默认值
def function1(a1,a2 = 4):
return a1 + a2
当函数在定义的时候,其中一个形式参数在定义的时候已经给定了默认值,则在函数调用的时候,如果不给顶该参数的值,那么它将采用默认值作为参数调用。
函数的返回值
在函数定义的时候,可以通过return来确定函数的返回值,这个返回值可以是各种形式的,用户可以根据需求返回不同类型的函数值,例如:
def func1():
a = 1.0
return a #返回数值
def func1():
a = 1.0
b = 10
reutnr a,b #返回元组
函数还可以返回更多其它类型的数据包括列表,字典;既然函数可以返回这些不同类型的数据,那么在调用函数的时候,函数的参数同样也可以是不同的数据类型。python中函数参数的传递类型是传址调用,这就说明如果在函数过程中对变量进行了修改,那么在函数调用结束后,传递进入的变量的值就是永久的改变,这一点需要小心注意。
传递任意数量的参数
def func1(*param):
print(param)
通过这种形式的函数定义,我们可以在调用函数的时候输入任意多的参数,这些参数都将会以元组的方式保存到param中。
位置实参和任意实参的结合
def func1(size,*param):
……………
在两中参数调用形式结合之后,可以灵活的将参数输入进行调整。
将函数写入在模块中
如果一个项目中,有一些函数需要频繁使用,那么可以将这些函数单独写在一个文件中当作模块,在需要使用它的时候,利用import函数将整个模块文件导入之后,使用即可。如果只是想单独的导入模块中的某一个函数可以使用from module_name import function _name
。当需要给导入的函数或者模块起一个新名字的时候可以使用as进行import module_name as new_name
,form module_name import function_name as new_name
。若想直接导入模块内的所有函数可以利用from module_name import *
,这个*号是正则表达式中的概念,它可以代表任何形式的函数命名。
7.类
class Dog():
"创建一个狗的实例"
def __init__(self,name,age):
self.name = name
self.age = age
def site(self):
print(self.name.title() + " is sitting.")
def roll_over(self):
print(self.name.title() + " is roll_over")
dog = Dog('A',12)
方法__init__() 是一个特殊的方法, 每当你根据Dog 类创建新实例时, Python都会自动运行它。 在这个方法的名称中, 开头和末尾各有两个下划线, 这是一种约定, 旨在避免Python默认方法与普通方法发生名称冲突。 这个特殊的方法__inti__()中,self是必不可少的参数,而且它必须位于所有参数的第一个。
Python在调用__init__()这个方法来创建Dog实例的时候,会自动传入一个实参self;每一个在类内定义的方法,都会自动传入实参self,它是一个指向实例本身的引用,可以让实例能够访问类中的属性和各种方法。 在__init__() 的定义中我们看到有两个前缀为self的定义的变量,它表明这个变量可以被类中定义的所有函数方法使用(相当于类中的一个全局变量)。
在上面定义的Dog类中,可以看到,要定义具体的实例,该实例的属性是通过__init__()中的参数来进行设置的(name,age)。如果我们想给我们定义的类一个默认的属性,那么就需要在__init__()定义的时候,来给定这个默认的参数,以self为前缀,它同样可以被所有的类内定义的函数方法使用。
class Car():
def __init__(self,name,size):
self.name = name
self.size = size
self.color = 'black'
def run(self):
print(self.name.title() + ' is running')
def col(self):
print(self.name.title() + ' is ' + self.color.title())
car1 = Car('car1',12)
car1.run()
car1.col()
Car1 is running
Car1 is Black
在上面这个定义的实例中,Car类中定义了一个self.color的默认属性,在构建具体实例的时候,不需要去给该属性赋值。 如果要对一个实例的某个属性进行修改,有两种方法,一种是直接通过对赋值的方式进行修改,第二种是在定义抽象类的时候,定义一个可以进行参数修改的函数方法来修改
class Car():
def __init__(self,name,size):
self.name = name
self.size = size
self.color = 'black'
def run(self):
print(self.name.title() + ' is running')
def col(self):
print(self.name.title() + ' is ' + self.color.title())
def change_color(self,color):
self.color = color
car1 = Car('car1',12)
car1.col()
car1.color = 'red'
car1.col()
car1.change_color('pink')
car1.col()
Car1 is Black
Car1 is Red
Car1 is Pink
继承
在程序编写的过程中,如果我么要编写的类,是某一个已经存在的类的特殊版本,那么我们可以同过继承的方式,在已经存在的类的基础上,以继承的方式,来构建新的类。通过继承的方法,已经存在的类(父类),中的所有方法和属性都会被新构建的类(子类)所继承,而且在这个基础上,还可以对子类增加新的属性和方法,这些是父类所没有的。
比方说我们现在有一个父类Car,现在需要在它的基础上来构建一个新的类。
class Car():
def __init__(self,name,size):
self.name = name
self.size = size
self.color = 'black'
def run(self):
print(self.name.title() + ' is running')
def col(self):
print(self.name.title() + ' is ' + self.color.title())
def change_color(self,color):
self.color = color
class eleCar(Car): # 在定义子类时,需要在括号内说明它要继承的父类是哪一个
def __init__(self,name,size):
self.name = name
self.size = size
'''继承父类的属性'''
super().__init__(name,size)
car2 = eleCar('Car2',12)
car2.run()
Car2 is running
super() 是一个特殊函数, 帮助Python将父类和子类关联起来,它让子类调用了父类的初始化方法,也就是让子类继承了父类的所有属性。 在继承了父类的属性和方法之后,子类就可以来定义自己特有的属性和方法了。
class Car():
def __init__(self,name,size):
self.name = name
self.size = size
self.color = 'black'
def run(self):
print(self.name.title() + ' is running')
def col(self):
print(self.name.title() + ' is ' + self.color.title())
def change_color(self,color):
self.color = color
class eleCar(Car): # 在定义子类时,需要在括号内说明它要继承的父类是哪一个
def __init__(self,name,size,battery):
self.name = name
self.size = size
'''初始化父类的属性'''
super().__init__(name,size)
'''定义子类特有的属性和方法'''
self.battery = battery
def battery_size(self):
print(self.name.title() + ' battery is ' + str(self.battery))
car2 = eleCar('Car2',12,70)
car2.battery_size()
Car2 battery is 70
重写父类方法
在子类继承父类的过程中,如果从父类继承的某个函数方法,对子类来所并不适用,那么可以通过在子类里面重新定义这个方法,来达到对父类方法重写的目的。
将实例用作属性
使用代码模拟实物时, 你可能会发现自己给类添加的细节越来越多: 属性和方法清单以及文件都越来越长。 在这种情况下, 可能需要将类的一部分作为一个独立的类提取出来。你可以将大型类拆分成多个协同工作的小类。
class Car():
def __init__(self,name,size):
self.name = name
self.size = size
self.color = 'black'
def run(self):
print(self.name.title() + ' is running')
def col(self):
print(self.name.title() + ' is ' + self.color.title())
def change_color(self,color):
self.color = color
class battery():
def __init__(self,size = 70):
self.size = size
class eleCar(Car): # 在定义子类时,需要在括号内说明它要继承的父类是哪一个
def __init__(self,name,size):
self.name = name
self.size = size
'''初始化父类的属性'''
super().__init__(name,size)
'''定义子类特有的属性和方法'''
self.battery = battery()
car1 = eleCar('car1',12)
print(car1.battery.size)
70
如上所示,我们将eleCar中的battery属性通过一个具体的实例battery()给出,这样就可以通过battery类来给这个属性更加详细和丰富的描述 在类的定义和之前学习函数时函数的定义中,可以将它们视为等同地位的工具,所以class同样可以直接写在一个文件中的,当我们需要的时候,就可以通过和导入函数相同的方法来导入并且使用class
文件和异常
标准的文件读取流程为:
with open(‘pi_digits.txt’) as file_object: contents = file_object.read() print(contents)
这中文件读取的方式需要这个数据文件和当前运行的程序在同一个目录下面。当然可以利用文件的完整路径来进行数据读写。 当用这种方式将文件打开并且读取之后,file_object中包含的是整个文件的所有内容(可以这么理解),所以此时read函数将会加载整个文件内所有的内容。
filename = ‘pi_digits.txt’ with open(filename) as file_object: for line in file_object: print(line)
同样可以将所有的文件内容以行为单位,逐行输出。上面的代码中,由于文件中每一行末尾都有一个换行符,而且print也会进行自动换行,所以程序运行的时候,每一行内容中间都会有一个空行的存在,为了消除这个空行
with open(filename) as file_object: for line in file_object: print(line.rstrip())
可以将文本中每一行后面的多余的这个空行给消除。 我们还可以将文件的整个内容,以行为单位,读入一个列表之中。
filename = ‘pi_digits.txt’ with open(filename) as file_object: lines = file_object.readlines() for line in lines: print(line.rstrip())
标准的文件写入流程为:
filename = ‘programming.txt’ with open(filename, ‘w’) as file_object: file_object.write(“I love programming.")
每一次将数据写入到文件中之后,不会有换行符的加入,下一次的内容写入会接着上一次内容的末尾开始继续写入(在同一次文件打开过程中)。如果希望在同一次的文件打开过程中,依次写入的数据之间要换行,那么我们需要在每一次数据写入的时候认为的在最后加入**\n**来保证下次数据写入时从下一行开始。
在文件打开的时候,需要指定我们对该文件的操作方式open(filename,“操作方式”)。
异常
标准的异常处理流程为:
try: print(5/0) # 这里时你所要执行的代码 except ZeroDivisionError: #except后面的这个关键词,代表了你要在上面的执行代码区域内捕捉的是什么样的错误 print(“You can’t divide by zero!") # 下面这就是你捕捉到这中错误之后,希望后续的执行操作时什么
发生错误时, 如果程序还有工作没有完成, 妥善地处理错误就尤其重要。 这种情况经常会出现在要求用户提供输入的程序中; 如果程序能够妥善地处理无效输入, 就能再提示用户提供有效输入, 而不至于崩溃。
print(“Give me two numbers, and I’ll divide them.") print(“Enter ‘q’ to quit.") while True: first_number = input("\nFirst number: “) if first_number == ‘q’: break second_number = input(“Second number: “) try: answer = int(first_number) / int(second_number) except ZeroDivisionError: print(“You can’t divide by 0!") else: print(answer) # 在通过try-except进行了异常捕捉后,当try中的代码运行无误的时候,就会转到else后面的代码块执行