AI智能
改变未来

【学习笔记】python


基础

  • print()每执行一次默认在最后加上了\\n,也就是默认会换行;
  • break可以立即退出循环语句,包括else;pass是用来在循环或者判断中进行占位的(比如暂时没想好功能该怎么写,就先占位);
- == != 比较的是对象的值是否相等;- is  is not 比较的是对象的id是否相等(也就是比较是否是同一个对象)

序列

序列就是用来保存一组有序的数据,所有的数据在序列中都有唯一的索引;

  • 可变序列:列表(list);
  • 不可变序列:字符串(str),元祖(tuple);
# 遍历序列for s in stus:print(s)     # 每执行一次将序列中的元素赋给变量srange(3,0,-1) #[3,2,1],都是左闭右开;range就是生成一个自然数的序列;for i in range(30):代码块    #循环30次

可变对象

每个对象都保存了三个数据:

  • id(标识/地址)
  • type(类型)
  • value(值)

列表就是可变对象,可变对象是说其值(value)是可变的;

a[0] = 10# 这个是在改对象,不会改变变量的指向,只是指向的变量的值变了;a = [4,5,6]# 这个是在改变量,会改变变量指向的对象;

列表

  • 列表就是存储对象的对象;
#列表的切片;stus[-1]  #从倒数第一个开始;stus[0:2] #第一个元素和第二个元素;左闭右开;stus[0:5:-1]  #[起始:结束:步长],if步长是负数表示从后开始;步长不能是0;s.index[\'a\',1,3]   #获取a在列表中在[1,3)中首次出现的索引;s.count[\'a\']   #获取a在列表中出现的次数;  这两个都是方法,必须通过xxx.method()来调用;# 列表的替换# 在给切片进行赋值时,只能使用序列stus[0:2] = [1,2,3] # 序列的个数可以和切片的个数不一致;stus[::2] = [1,2]  #当设置了步长时,两者个数必须相同;
  • 列表的方法
s.append(1)   # 向列表最后添加元素;s.insert(2,\'a\') #向列表的2索引处插入a;s.extend([1,2,3])  #参数必须是序列,扩展s序列;s.pop(2)   #删除索引为2的元素,有返回值;s.remove(2) #删除值为2的元素,if有多个值,只删第一个;s.clear()  #清空序列;s.reverse() #反转列表;s.sort()  #对列表排序,默认是升序,可以传递参数reverse=true来变成降序;

元组(tuple)

  • 元祖就是不可变的列表
t = ()  # 创建空元组;t = 1,2,3,4  # 当元组不为空时,括号可以不写;t = 1,  # if元组不为空,至少要有一个逗号;a,b,c,d = t # 元组的解包,这时候a=1,b=2;# 所以if想要交换两个元素,其实可以直接a,b = b,a  # b,a就是一个元组,进行了解包;# 在对一个元组进行解包时,变量的数量必须和元组中的元素的数量一致# 也可以在变量前边添加一个*,这样变量将会获取元组中所有剩余的元素a , b , *c = t # c = [3,4];# 解包是对所有序列都可以的,不仅是元组;

字典(dict)

  • 列表存储数据很好,但是查询的性能很差;而字典从查询效率很高;
  • 字典中每个对象都有一个名字(key),而每个对象就是value;这样一个键值对称为一项(item);
  • 字典的值可以是任意对象;字典的键可以是任意的不可变对象(int、str、bool、tuple …),但是一般我们都会使用str
d = {}   #空字典d = {\'name\':a, \'age\':18}print(d[\'name]\')   # a;注意name一定要加引号;----------------------# 使用 dict()函数来创建字典# 每一个参数都是一个键值对,参数名就是键,参数名就是值(这种方式创建的字典,key都是字符串)d = dict(name=\'孙悟空\',age=18,gender=\'男\')len(d)  #获取字典中键值对的个数;in/not in   #字典中是否有指定的键;-----------------------d[\'name\']   #获取字典的值;d.get(\'hello\',default)  # if hello不存在,会返回默认值;-----------------------d[\'name\'] = \'sunwukong\' # 修改字典的key-valuesetdefault(key, default) 可以用来向字典中添加key-value#   如果key已经存在于字典中,则返回key的值,不会对字典做任何操作#   如果key不存在,则向字典中添加这个key,并设置valued = {\'a\':1,\'b\':2,\'c\':3}d2 = {\'d\':4,\'e\':5,\'f\':6, \'a\':7}d.update(d2)  #将d2中的键值对添加到d,if 有相同的key会进行替代;-----------------------del d[\'name\']  # 删除键值对;result = d.pop(\'name\') #孙悟空,返回value;d.clear()  # 清空字典;-----------------------d1 = d2  # 两个指向的是同一个对象,修改一个另一个也会变;d1 = d2.copy # 这是复制品,是相互独立;注意,浅复制会简单复制对象内部的值,如果值也是一个可变对象,这个可变对象不会被复制d = {\'a\':{\'name\':\'孙悟空\',\'age\':18},\'b\':2,\'c\':3}d2 = d.copy()d2[\'a\'][\'name\'] = \'猪八戒\'  # d和d2都会变成猪八戒;-----------------------for k in d.keys():print(d[k])    #通过keys()遍历;for v in d.values():print(v)       #通过values()遍历:for k,v in d.items():print(k, \'=\', v)  #items()会返回字典中所有的项;# 会返回一个序列,序列中包含双值子序列,[(\'name\',a),(\'age\',18)],这时候赋值其实是解包;

集合(set)

  • 集合和列表非常相似
  • 不同点:
    1.集合中只能存储不可变对象 ( s= {[1,2,3]},这就是错误的,因为列表是可变的)
    2.集合中存储的对象是无序(不是按照元素的插入顺序保存)
    3.集合中不能出现重复的元素
s = {1,2,3}   #创建集合;s = set([1,2,1]) # set可以将列表和字典变为集合,字典转的时候,只有键;len(s)  # 元素数量;in/not in-----------------------s.add(4)  # 增加元素;s1.upadte(s2) # 将s2中的元素添加到s1中;-----------------------s.pop() # 随机删除集合中的一个元素;s.remove # 删除集合中的指定元素;s.clear()-----------------------s1 & s2 # 集合的交集;s1 | s2 # 集合的并集;s1 - s2 # 集合的差集;s1 ^ s2 # 集合的异或集:获取只在一个集合中出现的元素;s1 <= s2 # s1 是否是s2的子集s1 < s2 # s1 是否是s2的真子集

函数

  • 函数也是对象;函数可以用来保存一些可执行的代码,并且可以在需要时,对这些语句进行多次的调用
def fn(a,b):代码块    #fn是函数对象,fn()调用函数;# 函数在调用时,解析器不会检查实参的类型;实参可以传递任意类型;比如列表甚至是函数都行(fn(fn1));def fn1(*a,b):代码块  #可变参数,会将所有的实参保存到一个元组中(装包)# 可变参数不是必须写在最后,但是注意,带*的参数后的所有参数,必须以关键字参数的形式传递# *形参不能接收关键字参数;# **形参可以接收关键字参数,会将这些参数统一保存到一个字典中;**参数必须在所有参数的最后;----------------------------t = (1,2)fn(*t)#传递实参时,可以在序列类型的参数前添加星号,这样他会自动将序列中的元素依次作为参数传递(解包),序列的个数必须和参数个数相同;# 同样,也可以用**来对字典进行解包,字典的key和参数形参名一样;----------------------------return 后面可以跟任意的值,甚至可以是函数;# 文档字符串def fn(a:int,b:bool,c:str=\'hello\') -> int:#这些里面的类型没有任何意义,仅仅是指示说明;···可以写一些说明文字···----------------------------if 想在函数内部修改全局变量的值,要加关键字 global;scope = locals()  # locals() 获取当前作用域的命名空间;# 命名空间其实就是一个字典,是一个专门用来存储变量的字典;所以scope是一个字典,这个字典就是当前作用域中所有的变量;scope[\'c\'] = 1000  # 向字典中添加键值对就相当于在全局中创建了一个变量c;globals_scope = globals()  #globals()这个函数可以在任意位置获取全局的命名空间;

高阶函数

  • 将函数作为参数,或者将函数作为返回值的函数是高阶函数;当将一个函数作为参数时,实际上是将指定的代码传递给了目标函数;
  • 这样的会就可以定制一些函数,然后将函数作为一种“规则”传递给目标函数,然后目标函数根据这种“规则”对参数(原料)做出相应的处理;

1.将函数作为参数传递:

filter()

filter()可以从序列中过滤出符合条件的元素,保存到一个新的序列中

  • 参数:
    1.函数,根据该函数来过滤序列(可迭代的结构)
    2.需要过滤的序列(可迭代的结构)
  • 返回值:
    过滤后的新序列(可迭代的结构)
匿名函数(lambda函数表达式)

有时候一个函数用一次就再也不用了,就可以用lambda表达式;匿名韩式一般都是作为参数使用的;
语法:lambda 参数列表 : 返回值

r = filter(lambda i : i > 5 , l)

2.将函数作为返回值

闭包
  • 将函数作为返回值返回,这就是一种闭包,通过闭包可以创建一些只有当前函数能访问的变量,可以将一些私有的数据藏到闭包里;
形成闭包的条件:1.函数嵌套;2.将内部函数作为返回值返回;3.内部函数必须要使用到外部函数的变量;
def fn():a = 10# 函数内部再定义一个函数def inner():print(\'我是fn2\' , a)# 将内部函数 inner作为返回值返回return inner# r是一个函数,是调用fn()后返回的函数# 这个函数实在fn()内部定义,并不是全局函数# 所以这个函数总是能访问到fn()函数内的变量r = fn()变量是里面能看到外面的,但是外面看不到里面的;这样闭包就可以了;

装饰器

在写程序的时候,if我们想扩展一个函数,但是我们要尽量不去动原始的函数,而是要遵从开闭原则,即开放对程序的扩展,而关闭对程序的修改;

装饰器其实就是一个函数,这个函数什么功能呢?它接收一个旧函数作为参数,然后在装饰器里对它进行装饰包装,然后以一个新函数作为返回;这样就可以在不修改原始函数的情况下对函数进行扩展;

可以直接在旧函数上声明@装饰器函数
可以给函数多个装饰器,装饰的时候从内向外;

对象

  • 类用大驼峰来命名:MyClass; 类也是对象,类就是一个用来创建对象的对象,一切皆对象!

  • 如果是函数调用,则调用时传几个参数,就会有几个实参;但是如果是方法调用,默认传递一个参数,这个实参是解析器自动传的,所以方法中至少要定义一个形参(self),这个默认传递的实参其实就是调用方法的对象本身!if是p1调的,那第一个参数就是p1,if是p2调的,那第一个参数就是p2;所以我们把这个参数命名为self,这个self就是指的是谁调用这个方法了,这个谁就是self;self就是当前对象

  • 当我们调用一个对象的属性时,解析器会先在当前对象中寻找是否含有该属性,
    如果有,则直接返回当前的对象的属性值,
    如果没有,则去当前对象的类对象中去寻找,如果有则返回类对象的属性值,如果类对象中依然没有,则报错!

  • 类对象和实例对象中都可以保存属性(方法)
    – 如果这个属性(方法)是所有的实例共享的,则应该将其保存到类对象中
    – 如果这个属性(方法)是某个实例独有,则应该保存到实例对象中

  • 在python中,xxx 称为特殊方法,或者称为魔术方法;这种方法不需要我们自己调用,会在一些时刻自动调用;

p1 = Person()的运行流程1.创建一个变量p12.在内存中创建一个新变量,这个变量的类型是Person3.__init__(self)方法执行4.将对象的id(地址)赋值给变量
  • 使用__开头的属性,实际上依然可以在外部访问,所以这种方式我们一般不用,(因为其实就是python将__name自己改名成了_类名__属性)一般我们会将一些私有属性(不希望被外部访问的属性)以_开头,一般情况下,使用_开头的属性都是私有属性,没有特殊需要不要修改私有属性

  • 继承,在类的括号里写父类,if没写,就是继承自object.

issubclass(a,b)  检查a是否是b的子类isinstance(a,A)  检查a是否是A的实例

父类中所有的方法和属性都可以被继承,包括特殊方法__init__,可以重写初始化方法,if想要增添多个属性,那可以调用super()来调用当前类的父类,然后再增添自己特有的就行了

# 父类中的所有方法都会被子类继承,包括特殊方法,也可以重写特殊方法class Dog(Animal):def __init__(self,name,age):# 希望可以直接调用父类的__init__来初始化父类中定义的属性# super() 可以用来获取当前类的父类,#   并且通过super()返回对象调用父类方法时,不需要传递selfsuper().__init__(name)self._age = age

python中可以多重继承:

class C(A,B):pass# C继承自两个父类,AB,ifA,B中有同名的方法,会先调用A的,
  • 多态:在函数的参数中,if要传入一个对象,其实不关注对象是什么类型的,只关注这个对象是否有某些属性和方法,只要有某些属性和方法,那就可以传递进去,这样保证了程序的灵活性;
  • 类属性可以通过A.属性和a.属性访问,实例属性只能通过a.属性访问,类.属性无法访问;在类中以self作为第一个参数的方法是实例方法,实例方法可以通过类和实例调用,通过实例调用时,会自动将当前对象传递给self,但是通过类调用时,不会自动传,所有,A.fangfa(a) = a.fangfa()
# 类方法# 在类内部使用 @classmethod 来修饰的方法属于类方法# 类方法的第一个参数是cls,也会被自动传递,cls就是当前的类对象#   类方法和实例方法的区别,实例方法的第一个参数是self,而类方法的第一个参数是cls#   类方法可以通过类去调用,也可以通过实例调用,没有区别@classmethoddef test_2(cls):print(\'这是test_2方法,他是一个类方法~~~ \',cls)print(cls.count)# 静态方法# 在类中使用 @staticmethod 来修饰的方法属于静态方法# 静态方法不需要指定任何的默认参数,静态方法可以通过类和实例去调用# 静态方法,基本上是一个和当前类无关的方法,它只是一个保存到当前类中的函数# 静态方法一般都是一些工具方法,和当前类无关@staticmethoddef test_3():print(\'test_3执行了~~~\')
  • 特殊方法也叫魔法方法,一般不需要手动调用,在一些特殊的时候会自动执行,以__开始,比如__init__在对象创建时调用,__del__会在结束时调用,进行垃圾回收

  • 一个py文件就是一个模块,模块也是一个对象!在每一个模块内部都有一个__name__属性,通过这个属性可以获取到模块的名字__name__属性值为 __main__的模块是主模块,一个程序中只会有一个主模块,主模块就是我们直接通过 python 执行的模块

  • 一个文件夹就是一个包,一个包里可以有多个模块,包中必须含有一个__init__.py文件,一个包里会有__pycache__文件夹,这是模块的缓存文件, py代码在执行前,需要被解析器先转换为机器码,然后再执行,所以我们在使用模块(包)时,也需要将模块的代码先转换为机器码然后再交由计算机执行而为了提高程序运行的性能,python会在编译过一次以后,将代码保存到一个缓存文件中,这样在下次加载这个模块(包)时,就可以不再重新编译而是直接加载缓存中编译好的代码即可

异常

try:代码块(可能出现错误的语句)except 异常类型 as 异常名:代码块(出现错误以后的处理方式)else:代码块(没出错时要执行的语句))finally:代码块(该代码块总会执行)
  • 异常也是一个对象,比如 : ZeroDivisionError类的对象专门用来表示除0的异常NameError类的对象专门用来处理变量错误的异常
  • Exception 是所有异常类的父类,所以如果except后跟的是Exception,他也会捕获到所有的异常;可以在异常类后边跟着一个 as xx 此时xx就是异常对象
  • 可以使用 raise 语句来抛出异常,raise语句后需要跟一个异常类 或 异常的实例

文件

  • 打开文件,opne(file_name)会返回一个对象,if当前文件和目标文件在同一级目录下,则直接写名字就可以,其他的时候就必须用路径了。可以使用..来向上返回一级目录
  • read()用来读,会将内容保存为一个字符串返回;
  • 关闭文件;对象.close(),这时候其实经常是忘记的,所以有了with..as语句
with open(file_name) as file_obj:   #这其实就是和file_obj = open(file_name)一样,当出去这个with后,会自动关闭;#打开file_name并返回一个变量file_objfile_obj.read()
with open(file_name , \'x\' , encoding=\'utf-8\') as file_obj:# 使用open()打开文件时必须要指定打开文件所要做的操作(读、写、追加)# 如果不指定操作类型,则默认是 读取文件 , 而读取文件时是不能向文件中写入的# r 表示只读的# w 表示是可写的,使用w来写入文件时,如果文件不存在会创建文件,如果文件存在则会截断文件#   截断文件指删除原来文件中的所有内容# a 表示追加内容,如果文件不存在会创建文件,如果文件存在则会向文件中追加内容# x 用来新建文件,如果文件不存在则创建,存在则报错# + 为操作符增加功能#   r+ 即可读又可写,文件不存在会报错
# seek() 可以修改当前读取的位置seek()需要两个参数第一个 是要切换到的位置第二个 计算位置方式可选值:0 从头计算,默认值1 从当前位置计算2 从最后位置开始计算# tell() 方法用来查看当前读取的位置
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 【学习笔记】python