2024年Python最全【Python学习教程】Python类和对象_python中类和对象的讲解(1),2024年最新研发岗面试题

如果你也是看准了Python,想自学Python,在这里为大家准备了丰厚的免费学习大礼包,带大家一起学习,给大家剖析Python兼职、就业行情前景的这些事儿。

一、Python所有方向的学习路线

Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

二、学习软件

工欲善其必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

三、全套PDF电子书

书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。

四、入门学习视频

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

四、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

五、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

成为一个Python程序员专家或许需要花费数年时间,但是打下坚实的基础只要几周就可以,如果你按照我提供的学习路线以及资料有意识地去实践,你就有很大可能成功!
最后祝你好运!!!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!


这行代码的含义是创建一个名为 zhangsan 的 TheFirstDemo 类对象。运行代码可看到如下结果:


调用构造方法


显然,在创建 zhangsan 这个对象时,隐式调用了我们手动创建的 **init**() 构造方法。


不仅如此,在 **init**() 构造方法中,除了 self 参数外,还可以自定义一些参数,参数之间使用逗号“,”进行分割。例如,下面的代码在创建 **init**() 方法时,额外指定了 2 个参数:



class CLanguage:
‘’‘这是一个学习Python定义的一个类’‘’
def __init__(self,name,add):
print(name,“的网址为:”,add)
#创建 add 对象,并传递参数给构造函数
add = CLanguage(“C语言中文网”,“http://c.biancheng.net”)


注意,由于创建对象时会调用类的构造方法,如果构造函数有多个参数时,需要手动传递参数,传递方式如代码中所示(后续章节会做详细讲解)。


运行以上代码,执行结果为:


C语言中文网 的网址为: http://c.biancheng.net


可以看到,虽然构造方法中有 self、name、add 3 个参数,但实际需要传参的仅有 name 和 add,也就是说,self 不需要手动传递参数。


关于 self 参数,后续章节会做详细介绍,这里只需要知道,在创建类对象时,无需给 self 传参即可。


## Python类对象的创建和使用


通过前面章节的学习,我们已经学会如何定义一个类,但要想使用它,必须创建该类的对象。



> 
> 创建类对象的过程,又称为类的实例化。
> 
> 
> 


### [Python]( )类的实例化


对已定义好的类进行实例化,其语法格式如下:


类名(参数)


定义类时,如果没有手动添加 **init**() 构造方法,又或者添加的 **init**() 中仅有一个 self 参数,则创建类对象时的参数可以省略不写。


例如,如下代码创建了名为 CLanguage 的类,并对其进行了实例化:



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类对象的使用


定义的类只有进行实例化,也就是使用该类创建对象之后,才能得到利用。总的来说,实例化后的类对象可以执行以下操作:


* 访问或修改类对象具有的实例变量,甚至可以添加新的实例变量或者删除已有的实例变量;
* 调用类对象的方法,包括调用现有的方法,以及给类对象动态添加方法。


##### 类对象访问变量或方法


使用已创建好的类对象访问类中实例变量的语法格式如下:


类对象名.变量名


使用类对象调用类中方法的语法格式如下:


对象名.方法名(参数)


注意,对象名和变量名以及方法名之间用点 “.” 连接。


例如,下面代码演示了如何通过 clanguage 对象调用类中的实例变量和方法:



#输出name和add实例变量的值
print(clanguage.name,clanguage.add)
#修改实例变量的值
clanguage.name=“Python教程”
clanguage.add=“http://c.biancheng.net/python”
#调用clanguage的say()方法
clanguage.say(“人生苦短,我用Python”)
#再次输出name和add的值
print(clanguage.name,clanguage.add)


程序运行结果为:


C语言中文网 网址为: http://c.biancheng.net  
 C语言中文网 http://c.biancheng.net  
 人生苦短,我用Python  
 Python教程 http://c.biancheng.net/python


##### 给类对象动态添加/删除变量


Python 支持为已创建好的对象动态增加实例变量,方法也很简单,举个例子:



为clanguage对象增加一个money实例变量

clanguage.money= 159.9
print(clanguage.money)


运行结果为:


159.9


可以看到,通过直接增加一个新的实例变量并为其赋值,就成功地为 clanguage 对象添加了 money 变量。


既然能动态添加,那么是否能动态删除呢?答案是肯定的,使用 del 语句即可实现,例如:



#删除新添加的 money 实例变量
del clanguage.money
#再次尝试输出 money,此时会报错
print(clanguage.money)


运行程序会发现,结果显示 AttributeError 错误:


Traceback (most recent call last):  
 File “C:/Users/mengma/Desktop/1.py”, line 29, in   
 print(clanguage.money)  
 AttributeError: ‘CLanguage’ object has no attribute ‘money’


##### 给类对象动态添加方法


注意,初学者在理解下面内容之前,需明白 self 参数的含义和作用,可阅读《[Python self用法]( )》详细了解。


Python 也允许为对象动态增加方法。以本节开头的 Clanguage 类为例,由于其内部只包含一个 say() 方法,因此该类实例化出的 clanguage 对象也只包含一个 say() 方法。但其实,我们还可以为 clanguage 对象动态添加其它方法。


需要注意的一点是,为 clanguage 对象动态增加的方法,Python 不会自动将调用者自动绑定到第一个参数(即使将第一个参数命名为 self 也没用)。例如如下代码:



先定义一个函数

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() 函数为例:



def info(self,content):
print(“C语言中文网地址为:%s” % content)

导入MethodType

from types import MethodType
clanguage.info = MethodType(info, clanguage)

第一个参数已经绑定了,无需传入

clanguage.info(“http://c.biancheng.net”)


可以看到,由于使用 MethodType 包装 info() 函数时,已经将该函数的 self 参数绑定为 clanguage,因此后续再使用 info() 函数时,就不用再给 self 参数绑定值了。


## Python self用法详解


在定义类的过程中,无论是显式创建类的构造方法,还是向类中添加实例方法,都要求将 self 参数作为方法的第一个参数。例如,定义一个 Person 类:



class Person:
def __init__(self):
print(“正在执行构造方法”)
# 定义一个study()实例方法
def study(self,name):
print(name,“正在学Python”)


那么,self 到底扮演着什么样的角色呢?本节就对 self 参数做详细的介绍。


事实上,Python 只是规定,无论是构造方法还是实例方法,最少要包含一个参数,并没有规定该参数的具体名称。之所以将其命名为 self,只是程序员之间约定俗成的一种习惯,遵守这个约定,可以使我们编写的代码具有更好的可读性(大家一看到 self,就知道它的作用)。


那么,self 参数的具体作用是什么呢?打个比方,如果把类比作造房子的图纸,那么类实例化后的对象是真正可以住的房子。根据一张图纸(类),我们可以设计出成千上万的房子(类对象),每个房子长相都是类似的(都有相同的类变量和类方法),但它们都有各自的主人,那么如何对它们进行区分呢?


当然是通过 self 参数,它就相当于每个房子的门钥匙,可以保证每个房子的主人仅能进入自己的房子(每个类对象只能调用自己的类变量和类方法)。


如果你接触过其他面向对象的编程语言(例如 [C++]( )),其实 Python 类方法中的 self 参数就相当于 C++ 中的 this 指针。


也就是说,同一个类可以产生多个对象,当某个对象调用类方法时,该对象会把自身的引用作为第一个参数自动传给该方法,换句话说,Python 会自动绑定类方法的第一个参数指向调用该方法的对象。如此,Python解释器就能知道到底要操作哪个对象的方法了。


因此,程序在调用实例方法和构造方法时,不需要手动为第一个参数传值。例如,更改前面的 Person 类,如下所示:



class Person:
def __init__(self):
print(“正在执行构造方法”)
# 定义一个study()实例方法
def study(self):
print(self,“正在学Python”)
zhangsan = Person()
zhangsan.study()
lisi = Person()
lisi.study()


上面代码中,study() 中的 self 代表该方法的调用者,即谁调用该方法,那么 self 就代表谁。因此,该程序的运行结果为:


正在执行构造方法  
 <**main**.Person object at 0x0000021ADD7D21D0> 正在学Python  
 正在执行构造方法  
 <**main**.Person object at 0x0000021ADD7D2E48> 正在学Python


另外,对于构造函数中的 self 参数,其代表的是当前正在初始化的类对象。举个例子:



class Person:
name = “xxx”
def __init__(self,name):
self.name=name
zhangsan = Person(“zhangsan”)
print(zhangsan.name)
lisi = Person(“lisi”)
print(lisi.name)


运行结果为:


zhangsan  
 lisi


可以看到,zhangsan 在进行初始化时,调用的构造函数中 self 代表的是 zhangsan;而 lisi 在进行初始化时,调用的构造函数中 self 代表的是 lisi。


值得一提的是,除了类对象可以直接调用类方法,还有一种函数调用的方式,例如:



class Person:
def who(self):
print(self)
zhangsan = Person()
#第一种方式
zhangsan.who()
#第二种方式
who = zhangsan.who
who()#通过 who 变量调用zhangsan对象中的 who() 方法


运行结果为:


<**main**.Person object at 0x0000025C26F021D0>  
 <**main**.Person object at 0x0000025C26F021D0>


显然,无论采用哪种方法,self 所表示的都是实际调用该方法的对象。



> 
> 总之,无论是类中的构造函数还是普通的类方法,实际调用它们的谁,则第一个参数 self 就代表谁。
> 
> 
> 


## Python类变量和实例变量(类属性和实例属性)


无论是类属性还是类方法,都无法像普通变量或者函数那样,在类的外部直接使用它们。我们可以将类看做一个独立的空间,则类属性其实就是在类体中定义的变量,类方法是在类体中定义的函数。


前面章节提到过,在类体中,根据变量定义的位置不同,以及定义的方式不同,类属性又可细分为以下 3 种类型:


1. 类体中、所有函数之外:此范围定义的变量,称为类属性或类变量;
2. 类体中,所有函数内部:以“self.变量名”的方式定义的变量,称为实例属性或实例变量;
3. 类体中,所有函数内部:以“变量名=变量值”的方式定义的变量,称为局部变量。



> 
> 不仅如此,类方法也可细分为实例方法、静态方法和类方法,后续章节会做详细介绍。
> 
> 
> 


那么,类变量、实例变量以及局部变量之间有哪些不同呢?接下来就围绕此问题做详细地讲解。


### 类变量(类属性)


类变量指的是在类中,但在各个类方法外定义的变量。举个例子:



class CLanguage :
# 下面定义了2个类变量
name = “C语言中文网”
add = “http://c.biancheng.net”
# 下面定义了一个say实例方法
def say(self, content):
print(content)


上面程序中,name 和 add 就属于类变量。


类变量的特点是,所有类的实例化对象都同时共享类变量,也就是说,类变量在所有实例化对象中是作为公用资源存在的。类方法的调用方式有 2 种,既可以使用类名直接调用,也可以使用类的实例化对象调用。


比如,在 CLanguage 类的外部,添加如下代码:



#使用类名直接调用
print(CLanguage.name)
print(CLanguage.add)
#修改类变量的值
CLanguage.name = “Python教程”
CLanguage.add = “http://c.biancheng.net/python”
print(CLanguage.name)
print(CLanguage.add)


程序运行结果为:


C语言中文网  
 http://c.biancheng.net  
 Python教程  
 http://c.biancheng.net/python


可以看到,通过类名不仅可以调用类变量,也可以修改它的值。


当然,也可以使用类对象来调用所属类中的类变量(此方式不推荐使用,原因后续会讲)。例如,在 CLanguage 类的外部,添加如下代码:



clang = CLanguage()
print(clang.name)
print(clang.add)


运行程序,结果为:


C语言中文网  
 http://c.biancheng.net


注意,因为类变量为所有实例化对象共有,通过类名修改类变量的值,会影响所有的实例化对象。例如,在 CLanguage 类体外部,添加如下代码:



print(“修改前,各类对象中类变量的值:”)
clang1 = CLanguage()
print(clang1.name)
print(clang1.add)
clang2 = CLanguage()
print(clang2.name)
print(clang2.add)
print(“修改后,各类对象中类变量的值:”)
CLanguage.name = “Python教程”
CLanguage.add = “http://c.biancheng.net/python”
print(clang1.name)
print(clang1.add)
print(clang2.name)
print(clang2.add)


程序运行结果为:


修改前,各类对象中类变量的值:  
 C语言中文网  
 http://c.biancheng.net  
 C语言中文网  
 http://c.biancheng.net  
 修改后,各类对象中类变量的值:  
 Python教程  
 http://c.biancheng.net/python  
 Python教程  
 http://c.biancheng.net/python


显然,通过类名修改类变量,会作用到所有的实例化对象(例如这里的 clang1 和 clang2)。



> 
> 注意,通过类对象是无法修改类变量的。通过类对象对类变量赋值,其本质将不再是修改类变量的值,而是在给该对象定义新的实例变量(在讲实例变量时会进行详细介绍)。
> 
> 
> 


值得一提的是,除了可以通过类名访问类变量之外,还可以动态地为类和对象添加类变量。例如,在 CLanguage 类的基础上,添加以下代码:



clang = CLanguage()
CLanguage.catalog = 13
print(clang.catalog)


运行结果为:


13


### 实例变量(实例属性)


实例变量指的是在任意类方法内部,以“self.变量名”的方式定义的变量,其特点是只作用于调用方法的对象。另外,实例变量只能通过对象名访问,无法通过类名访问。


举个例子:



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 实例变量。


例如,在上面代码的基础上,添加如下语句:



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)


运行结果为:


C语言中文网  
 http://c.biancheng.net  
 C语言中文网  
 http://c.biancheng.net  
 13


前面讲过,通过类对象可以访问类变量,但无法修改类变量的值。这是因为,通过类对象修改类变量的值,不是在给“类变量赋值”,而是定义新的实例变量。例如,在 CLanguage 类体外,添加如下程序:



clang = CLanguage()
#clang访问类变量
print(clang.name)
print(clang.add)
clang.name = “Python教程”
clang.add = “http://c.biancheng.net/python”
#clang实例变量的值
print(clang.name)
print(clang.add)
#类变量的值
print(CLanguage.name)
print(CLanguage.add)


程序运行结果为:


C语言中文网  
 http://c.biancheng.net  
 Python教程  
 http://c.biancheng.net/python  
 C语言中文网  
 http://c.biancheng.net


显然,通过类对象是无法修改类变量的值的,本质其实是给 clang 对象新添加 name 和 add 这 2 个实例变量。



> 
> 类中,实例变量和类变量可以同名,但这种情况下使用类对象将无法调用类变量,它会首选实例变量,这也是不推荐“类变量使用对象名调用”的原因。
> 
> 
> 


另外,和类变量不同,通过某个对象修改实例变量的值,不会影响类的其它实例化对象,更不会影响同名的类变量。例如:



class CLanguage :
name = “xxx” #类变量
add = “http://” #类变量
def init(self):
self.name = “C语言中文网” #实例变量
self.add = “http://c.biancheng.net” #实例变量
# 下面定义了一个say实例方法
def say(self):
self.catalog = 13 #实例变量
clang = CLanguage()
#修改 clang 对象的实例变量
clang.name = “python教程”
clang.add = “http://c.biancheng.net/python”
print(clang.name)
print(clang.add)
clang2 = CLanguage()
print(clang2.name)
print(clang2.add)
#输出类变量的值
print(CLanguage.name)
print(CLanguage.add)


程序运行结果为:


python教程  
 http://c.biancheng.net/python  
 C语言中文网  
 http://c.biancheng.net  
 xxx  
 http://


不仅如此,Python 只支持为特定的对象添加实例变量。例如,在之前代码的基础上,为 clang 对象添加 money 实例变量,实现代码为:



clang.money = 30
print(clang.money)


### 局部变量


除了实例变量,类方法中还可以定义局部变量。和前者不同,局部变量直接以“变量名=值”的方式进行定义,例如:



class CLanguage :
# 下面定义了一个say实例方法
def count(self,money):
sale = 0.8*money
print(“优惠后的价格为:”,sale)
clang = CLanguage()
clang.count(100)


通常情况下,定义局部变量是为了所在类方法功能的实现。需要注意的一点是,局部变量只能用于所在函数中,函数执行完成后,局部变量也会被销毁。


## Python实例方法、静态方法和类方法详解(包含区别和用法)


和类属性一样,类方法也可以进行更细致的划分,具体可分为类方法、实例方法和静态方法。


和类属性的分类不同,对于初学者来说,区分这 3 种类方法是非常简单的,即采用 @classmethod 修饰的方法为类方法;采用 @staticmethod 修饰的方法为静态方法;不用任何修改的方法为实例方法。



> 
> 其中 @classmethod 和 @staticmethod 都是函数装饰器,后续章节会对其做详细介绍。
> 
> 
> 


接下来就给大家详细的介绍这 3 种类方法。


### [Python]( )类实例方法


通常情况下,在类中定义的方法默认都是实例方法。前面章节中,我们已经定义了不只一个实例方法。不仅如此,类的构造方法理论上也属于实例方法,只不过它比较特殊。


比如,下面的类中就用到了实例方法:



class CLanguage:
#类构造方法,也属于实例方法
def __init__(self):
self.name = “C语言中文网”
self.add = “http://c.biancheng.net”
# 下面定义了一个say实例方法
def say(self):
print(“正在调用 say() 实例方法”)


实例方法最大的特点就是,它最少也要包含一个 self 参数,用于绑定调用此方法的实例对象(Python 会自动完成绑定)。实例方法通常会用类对象直接调用,例如:



clang = CLanguage()
clang.say()


运行结果:


正在调用 say() 实例方法


当然,Python 也支持使用类名调用实例方法,但此方式需要手动给 self 参数传值。例如:



#类名调用实例方法,需手动给 self 参数传值
clang = CLanguage()
CLanguage.say(clang)


运行结果为:


正在调用 say() 实例方法



> 
> 有关使用类名直接调用实例方法的更多介绍,可阅读《[Python类调用实例方法]( )》一节。
> 
> 
> 


### Python类方法


Python 类方法和实例方法相似,它最少也要包含一个参数,只不过类方法中通常将其命名为 cls,Python 会自动将类本身绑定给 cls 参数(注意,绑定的不是类对象)。也就是说,我们在调用类方法时,无需显式为 cls 参数传参。


和 self 一样,cls 参数的命名也不是规定的(可以随意命名),只是 Python 程序员约定俗称的习惯而已。


和实例方法最大的不同在于,类方法需要使用`@classmethod`修饰符进行修饰,例如:



class CLanguage:
#类构造方法,也属于实例方法
def __init__(self):
self.name = “C语言中文网”
self.add = “http://c.biancheng.net”
#下面定义了一个类方法
@classmethod
def info(cls):
print(“正在调用类方法”,cls)



> 
> 注意,如果没有 @classmethod,则 Python 解释器会将 fly() 方法认定为实例方法,而不是类方法。
> 
> 
> 


类方法推荐使用类名直接调用,当然也可以使用实例对象来调用(不推荐)。例如,在上面 CLanguage 类的基础上,在该类外部添加如下代码:



#使用类名直接调用类方法
CLanguage.info()
#使用类对象调用类方法
clang = CLanguage()
clang.info()


运行结果为:


正在调用类方法 <class ‘**main**.CLanguage’>  
 正在调用类方法 <class ‘**main**.CLanguage’>


### Python类静态方法


静态方法,其实就是我们学过的函数,和函数唯一的区别是,静态方法定义在类这个空间(类命名空间)中,而函数则定义在程序所在的空间(全局命名空间)中。


静态方法没有类似 self、cls 这样的特殊参数,因此 Python 解释器不会对它包含的参数做任何类或对象的绑定。也正因为如此,类的静态方法中无法调用任何类属性和类方法。


静态方法需要使用`@staticmethod`修饰,例如:



class CLanguage:
@staticmethod
def info(name,add):
print(name,add)


静态方法的调用,既可以使用类名,也可以使用类对象,例如:



#使用类名直接调用静态方法
CLanguage.info(“C语言中文网”,“http://c.biancheng.net”)
#使用类对象调用静态方法
clang = CLanguage()
clang.info(“Python教程”,“http://c.biancheng.net/python”)


运行结果为:


C语言中文网 http://c.biancheng.net  
 Python教程 http://c.biancheng.net/python


在实际编程中,几乎不会用到类方法和静态方法,因为我们完全可以使用函数代替它们实现想要的功能,但在一些特殊的场景中(例如工厂模式中),使用类方法和静态方法也是很不错的选择。


## Python类调用实例方法


通过前面的学习,类方法大体分为 3 类,分别是类方法、实例方法和静态方法,其中实例方法用的是最多的。我们知道,实例方法的调用方式其实有 2 种,既可以采用类对象调用,也可以直接通过类名调用。


通常情况下,我们习惯使用类对象调用类中的实例方法。但如果想用类调用实例方法,不能像如下这样:



class CLanguage:
def info(self):
print(“我正在学 Python”)
#通过类名直接调用实例方法
CLanguage.info()


运行上面代码,程序会报出如下错误:


Traceback (most recent call last):  
 File “D:\python3.6\demo.py”, line 5, in   
 CLanguage.info()  
 TypeError: info() missing 1 required positional argument: ‘self’


其中,最后一行报错信息提示我们,调用 info() 类方式时缺少给 self 参数传参。这意味着,和使用类对象调用实例方法不同,通过类名直接调用实例方法时,Python 并不会自动给 self 参数传值。



> 
> 读者想想也应该明白,self 参数需要的是方法的实际调用者(是类对象),而这里只提供了类名,当然无法自动传值。
> 
> 
> 


因此,如果想通过类名直接调用实例方法,就必须手动为 self 参数传值。例如修改上面的代码为:



class CLanguage:
def info(self):
print(“我正在学 Python”)
clang = CLanguage()
#通过类名直接调用实例方法
CLanguage.info(clang)


再次运行程序,结果为:


我正在学 Python


可以看到,通过手动将 clang 这个类对象传给了 self 参数,使得程序得以正确执行。实际上,这里调用实例方法的形式完全是等价于 `clang.info()。`


值得一提的是,上面的报错信息只是让我们手动为 self 参数传值,但并没有规定必须传一个该类的对象,其实完全可以任意传入一个参数,例如:



class CLanguage:
def info(self):
print(self,“正在学 Python”)
#通过类名直接调用实例方法
CLanguage.info(“zhangsan”)


运行结果为:


zhangsan 正在学 Python


可以看到,“zhangsan” 这个字符串传给了 info() 方法的 self 参数。显然,无论是 info() 方法中使用 self 参数调用其它类方法,还是使用 self 参数定义新的实例变量,胡乱的给 self 参数传参都将会导致程序运行崩溃。


总的来说,Python 中允许使用类名直接调用实例方法,但必须手动为该方法的第一个 self 参数传递参数,这种调用方法的方式被称为“非绑定方法”。



> 
> 用类的实例对象访问类成员的方式称为绑定方法,而用类名调用类成员的方式称为非绑定方法。
> 
> 
> 


## 浅谈Python类命名空间


前面章节已经不只一次提到,Python 类体中的代码位于独立的命名空间(称为类命名空间)中。换句话说,所有用 class 关键字修饰的代码块,都可以看做是位于独立的命名空间中。



> 
> 和类命名空间相对的是全局命名空间,即整个 Python 程序默认都位于全局命名空间中。而类体则独立位于类命名空间中。
> 
> 
> 


我们一开始学习类时就已经提到,类其实是由多个类属性和类方法构成,而类属性其实就是定义在类这个独立空间中的变量,而类方法其实就是定义在类空间中的函数,和定义在全局命名空间中的变量和函数相比,并没有明显的不同。


举个例子:



#全局空间定义变量
name = “C语言中文网”

现在能在网上找到很多很多的学习资源,有免费的也有收费的,当我拿到1套比较全的学习资源之前,我并没着急去看第1节,我而是去审视这套资源是否值得学习,有时候也会去问一些学长的意见,如果可以之后,我会对这套学习资源做1个学习计划,我的学习计划主要包括规划图和学习进度表。

分享给大家这份我薅到的免费视频资料,质量还不错,大家可以跟着学习

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值