# all_python_study **Repository Path**: binary-boy/all_python_study ## Basic Information - **Project Name**: all_python_study - **Description**: python基础以及进阶、面试。记录python学习路径以及过程、面试问题 - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-07-04 - **Last Updated**: 2022-08-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # all_python_study #### 介绍 python基础以及进阶、面试,用于记录python学习、面试 ## 一 、类与对象 ```python class tortoise: bodyColor = "绿色" footNum = 4 weight = 10 hasShell = True #会爬 def crawl(self): print("乌龟会爬") #会吃东西 def eat(self): print("乌龟吃东西") #会睡觉 def sleep(self): print("乌龟在睡觉") #会缩到壳里 def protect(self): print("乌龟缩进了壳里") ``` 面向对象中,常用术语包括: - 类:可以理解是一个模板,通过它可以创建出无数个具体实例。比如,前面编写的 tortoise 表示的只是乌龟这个物种,通过它可以创建出无数个实例来代表各种不同特征的乌龟(这一过程又称为类的实例化)。 - 对象:类并不能直接使用,通过类创建出的实例(又称对象)才能使用。这有点像汽车图纸和汽车的关系,图纸本身(类)并不能为人们使用,通过图纸创建出的一辆辆车(对象)才能使用。 - 属性:类中的所有变量称为属性。例如,tortoise 这个类中,bodyColor、footNum、weight、hasShell 都是这个类拥有的属性。 - 方法:类中的所有函数通常称为方法。不过,和函数所有不同的是,类方法至少要包含一个 self 参数(后续会做详细介绍)。例如,tortoise 类中,crawl()、eat()、sleep()、protect() 都是这个类所拥有的方法,类方法无法单独使用,只能和类的对象一起使用。 在 Python 中,所有的变量其实也都是对象,包括**整形(int)、浮点型(float)、字符串(str)、列表(list)、元组(tuple)、字典(dict)和集合(set)**。以字典(dict)为例,它包含多个函数供我们使用,例如使用 keys() 获取字典中所有的键,使用 values() 获取字典中所有的值,使用 item() 获取字典中所有的键值对,等等。 ### 1、Python __ init__()类构造方法 在创建类时,我们可以手动添加一个\__ __init__() __方法,该方法是一个特殊的类实例方法,称为**构造方法(或构造函数)**。 \____init__()__ 方法可以包含多个参数,但必须包含一个名为 self 的参数,且必须作为第一个参数。也就是说,类的构造方法最少也要有一个 self 参数。 ### 2、Python 类的实例化 ```python class CLanguage : # 下面定义了2个类变量 name = "C语言中文网" add = "http://c.biancheng.net" def __init__(self,name,add): #下面定义 2 个实例变量 self.name = name self.add = add print(name,"网址为:",add) # 下面定义了一个say实例方法 def say(self, content): print(content) # 将该CLanguage对象赋给clanguage变量 clanguage = CLanguage("C语言中文网","http://c.biancheng.net") ``` 在上面的程序中,由于构造方法除 self 参数外,还包含 2 个参数,**且这 2 个参数没有设置默认参数,因此在实例化类对象时,需要传入相应的 name 值和 add 值**(self 参数是特殊参数,不需要手动传值,Python 会自动传给它值)。 类变量和实例变量,简单地理解,定义在各个类方法之外(包含在类中)的变量为类变量(或者类属性),定义在类方法中的变量为实例变量(或者实例属性) #### Python类对象的使用 定义的类只有进行实例化,也就是使用该类创建对象之后,才能得到利用。总的来说,实例化后的类对象可以执行以下操作: - 访问或修改类对象具有的**实例变量**,甚至可以添加**新的实例变量或者删除已有的实例变量**; - 调用类对象的方法,包括调用现有的方法,以及给类对象动态添加方法。 #### 给类对象动态添加/删除变量 Python 支持为已创建好的对象动态增加**实例变量**,方法也很简单,举个例子: ```python # 为clanguage对象增加一个money实例变量 clanguage.money= 159.9 print(clanguage.money) ``` 既然能动态添加,那么是否能动态删除呢?答案是肯定的,使用 del 语句即可实现,例如: ```python #删除新添加的 money 实例变量 del clanguage.money #再次尝试输出 money,此时会报错 print(clanguage.money) ``` #### 给类对象动态添加方法 Python 也允许为对象动态增加方法。以本节开头的 Clanguage 类为例,由于其内部只包含一个 say() 方法,因此该类实例化出的 clanguage 对象也只包含一个 say() 方法。但其实,我们还可以为 clanguage 对象动态添加其它方法。 需要注意的一点是,为 clanguage 对象动态增加的方法,Python 不会自动将调用者自动绑定到第一个参数(即使将第一个参数命名为 self 也没用)。例如如下代码: ```python # 先定义一个函数 def info(self): print("---info函数---", self) # 使用info对clanguage的foo方法赋值(动态绑定方法) clanguage.foo = info # Python不会自动将调用者绑定到第一个参数, # 因此程序需要手动将调用者绑定为第一个参数 clanguage.foo(clanguage) # ① # 使用lambda表达式为clanguage对象的bar方法赋值(动态绑定方法) clanguage.bar = lambda self: print('--lambda表达式--', self) clanguage.bar(clanguage) # ② ``` 上面的第 5 行和第 11 行代码分别使用函数、lambda 表达式为 clanguage 对象动态增加了方法,但对于动态增加的方法,Python 不会自动将方法调用者绑定到它们的第一个参数,因此程序必须手动为第一个参数传入参数值,如上面程序中 ① 号、② 号代码所示。 有没有不用手动给 self 传值的方法呢?通过借助 types 模块下的 MethodType 可以实现,仍以上面的 info() 函数为例: ```python def info(self,content): print("C语言中文网地址为:%s" % content) # 导入MethodType from types import MethodType clanguage.info = MethodType(info, clanguage) # 第一个参数已经绑定了,无需传入 clanguage.info("http://c.biancheng.net") ``` ### 3、Python self用法详解 self 参数的具体作用是什么呢?打个比方,如果把类比作造房子的图纸,那么类实例化后的对象是真正可以住的房子。根据一张图纸(类),我们可以设计出成千上万的房子(类对象),每个房子长相都是类似的(都有相同的类变量和类方法),但它们都有各自的主人,那么如何对它们进行区分呢? 当然是通过 **self 参数,它就相当于每个房子的门钥匙**,可以保证每个房子的主人仅能进入自己的房子(每个类对象只能调用自己的类变量和类方法)。 **可以把 self 理解为当前类的地址**,Python 类方法中的 self 参数就相当于 **C++ 中的 this 指针**。 同一个类可以产生多个对象,当某个对象调用类方法时,该对象会把自身的引用作为第一个参数自动传给该方法,换句话说,Python 会自动绑定类方法的第一个参数指向调用该方法的对象。如此,Python解释器就能知道到底要操作哪个对象的方法了。 ### 4、Python类变量和实例变量(类属性和实例属性) 1. 类体中、所有函数之外:此范围定义的变量,称为类属性或类变量; 2. 类体中,所有函数内部:以“self.变量名”的方式定义的变量,称为实例属性或实例变量; 3. 类体中,所有函数内部:以“变量名=变量值”的方式定义的变量,称为局部变量。 #### 类变量(类属性) 类变量指的是在类中,但在各个类方法外定义的变量。举个例子: ```python class CLanguage : # 下面定义了2个类变量 name = "C语言中文网" add = "http://c.biancheng.net" # 下面定义了一个say实例方法 def say(self, content): print(content) ``` 上面程序中,name 和 add 就属于类变量。 类变量的特点是,所有**类的实例化对象都同时共享类变量**,也就是说,类变量在所有实例化对象中是作为公用资源存在的。类方法的调用方式有 2 种, 既可以使用类名直接调用,也可以使用类的实例化对象调用。 注意,因为类变量为所有实例化对象共有,通过类名修改类变量的值,会影响所有的实例化对象。通过类名修改类变量,会作用到所有的实例化对象 除了可以通过类名访问类变量之外,还可以动态地为类和对象添加类变量。例如,在 CLanguage 类的基础上,添加以下代码: ```python clang = CLanguage() CLanguage.catalog = 13 print(clang.catalog) ``` #### 实例变量(实例属性) 实例变量指的是在任意类方法内部,以“self.变量名”的方式定义的变量,其特点是只作用于调用方法的对象。另外,**实例变量只能通过对象名访问,无法通过类名访问。** ```python class CLanguage : def __init__(self): self.name = "C语言中文网" self.add = "http://c.biancheng.net" # 下面定义了一个say实例方法 def say(self): self.catalog = 13 ``` 此 CLanguage 类中,name、add 以及 catalog 都是实例变量。其中,由于 __init__() 函数在创建类对象时会自动调用,而 say() 方法需要类对象手动调用。因此,**CLanguage 类的类对象都会包含 name 和 add 实例变量,而只有调用了 say() 方法的类对象,才包含 catalog 实例变量。** ```python clang = CLanguage() print(clang.name) print(clang.add) #由于 clang 对象未调用 say() 方法,因此其没有 catalog 变量,下面这行代码会报错 #print(clang.catalog) clang2 = CLanguage() print(clang2.name) print(clang2.add) #只有调用 say(),才会拥有 catalog 实例变量 clang2.say() print(clang2.catalog) ``` ```python clang = CLanguage() print(clang.name) print(clang.add) #由于 clang 对象未调用 say() 方法,因此其没有 catalog 变量,下面这行代码会报错 #print(clang.catalog) clang2 = CLanguage() print(clang2.name) print(clang2.add) #只有调用 say(),才会拥有 catalog 实例变量 clang2.say() print(clang2.catalog) ``` 通过**类对象**可以访问**类变量**,**但无法修改类变量的值。这是因为,通过类对象修改类变量的值,不是在给“类变量赋值”,而是定义新的实例变量** 类中,实例变量和类变量可以同名,但这种情况下使用类对象将无法调用类变量,它会首选实例变量,这也是不推荐“类变量使用对象名调用”的原因。 #### 局部变量 除了实例变量,类方法中还可以定义局部变量。和前者不同,局部变量直接以“变量名=值”的方式进行定义,例如: ```python class CLanguage : # 下面定义了一个say实例方法 def count(self,money): sale = 0.8*money print("优惠后的价格为:",sale) clang = CLanguage() clang.count(100) ``` 通常情况下,定义局部变量是为了所在类方法功能的实现。需要注意的一点是,局部变量只能用于所在函数中,**函数执行完成后,局部变量也会被销毁。** ### 5、Python实例方法、静态方法和类方法详解 采用 @classmethod 修饰的方法为类方法;采用 @staticmethod 修饰的方法为静态方法;不用任何修改的方法为实例方法。 > 其中 @classmethod 和 @staticmethod 都是函数装饰器 #### [Python](http://c.biancheng.net/python/)类实例方法 在类中定义的方法默认都是实例方法 ```python class CLanguage: #类构造方法,也属于实例方法 def __init__(self): self.name = "C语言中文网" self.add = "http://c.biancheng.net" # 下面定义了一个say实例方法 def say(self): print("正在调用 say() 实例方法") ``` 实例方法最大的特点就是,它最少也要包含一个 self 参数,用于绑定调用此方法的实例对象(Python 会自动完成绑定)。实例方法通常会用类对象直接调用. Python 也支持使用类名调用实例方法,但此方式需要手动给 self 参数传值。例如: ```python #类名调用实例方法,需手动给 self 参数传值 clang = CLanguage() CLanguage.say(clang) ``` #### 类方法