文章目录
1. python类的成员函数为什么都要有self参数?
在定义类的过程中,无论是显式创建类的构造方法
,还是向类中添加实例方法
,都要求将 self
参数作为方法的第一个参数。例如,定义一个 Person 类:
class Person:
# 类的构造方法
def __init__(self):
print("正在执行构造方法")
# 定义一个study()实例方法
def study(self,name):
print(name,"正在学Python")
事实上,Python 只是规定,无论是构造方法还是实例方法,最少要包含一个参数,并没有规定该参数的具体名称
。之所以将其命名为 self
,只是程序员之间约定俗成的一种习惯
,遵守这个约定,可以使我们编写的代码具有更好的可读性(大家一看到 self,就知道它的作用)。
self 参数的具体作用是 代表 类实例化出的对象的地址
。目的是 让每个类对象 只能调用 自己的类变量和类方法
。
如果你接触过其他面向对象的编程语言(例如 C++),其实 Python 类方法中的 self 参数就相当于 C++ 中的 this 指针。
也就是说,同一个类可以产生多个对象,当某个对象调用类方法时,该对象会把自身的引用作为第一个参数自动传给该方法,换句话说,Python 会自动绑定类方法的第一个参数指向调用该方法的对象。如此,Python解释器就能知道到底要操作哪个对象的方法了。
若是去掉self参数,则会报这个错:TypeError: 类成员方法名() takes no arguments (1 given)
2. 为何调用类的成员函数,你不必给self赋值?
例子说明:
创建了一个类MyClass,实例化MyClass
得到了MyObject
这个对象,然后调用这个对象的方法MyObject.method(arg1,arg2)
,这个过程中,Python会自动转为Myclass.mehod(MyObject,arg1,arg2)
这就是Python的self的原理了。
即使你的类的方法不需要任何参数,但还是得给这个方法定义一个self参数,虽然我们在实例化调用的时候不用理会这个参数,不用给它赋值。
3. 类变量在不同位置定义有什么区别?
(1)类变量
类体中、所有函数之外:此范围定义的变量,称为类属性
或类变量
;
所有类的实例化对象都同时共享类变量
,也就是说,类变量在所有实例化对象中是作为公用资源存在的(通过类名修改类变量的值,会影响所有的实例化对象)。类方法的调用方式有 2 种,既可以使用类名直接调用
,也可以使用类的实例化对象调用(不推荐,见最后阐述)。
(2)实例变量
类体中,所有函数内部:以“self.变量名
”的方式定义的变量,称为实例属性
或实例变量
;
其特点是只作用于调用方法的对象。另外,实例变量只能通过对象名访问,无法通过类名访问。
(3)局部变量
类体中,所有函数内部:以“变量名=变量值
”的方式定义的变量,称为局部变量
。
通常情况下,定义局部变量是为了所在类方法功能的实现。需要注意的一点是,局部变量只能用于所在函数中,函数执行完成后,局部变量也会被销毁
。
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://
注意:
通过类对象是无法修改类变量的值的
,本质其实是给 clang 对象新添加 name 和 add 这 2 个实例变量。- 类中,
实例变量和类变量可以同名
,但这种情况下使用类对象将无法调用类变量,它会首选实例变量
,这也是不推荐“类变量使用对象名调用”的原因。
4. 实例方法、静态方法和类方法区别?
具体区别和用法可阅读 blog
(1)实例方法
通常情况下,在类中定义的方法默认都是实例方法。不仅如此,类的构造方法理论上也属于实例方法,只不过它比较特殊。
实例方法最大的特点就是,它最少也要包含一个 self 参数
,用于绑定调用此方法的实例对象(Python 会自动完成绑定)。实例方法通常会用类对象直接调用
class CLanguage:
#类构造方法,也属于实例方法
def __init__(self):
self.name = "C语言中文网"
self.add = "http://c.biancheng.net"
# 下面定义了一个say实例方法
def say(self):
print("正在调用 say() 实例方法")
调用方法:
clang = CLanguage()
clang.say()
或
#类名调用实例方法,需手动给 self 参数传值
clang = CLanguage()
CLanguage.say(clang)
(2)类方法
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)
调用方式:
#使用类名直接调用类方法
CLanguage.info()
#使用类对象调用类方法(不推荐!!!)
clang = CLanguage()
clang.info()
(3)静态方法
静态方法
,其实就是我们学过的函数,和函数唯一的区别是,静态方法定义在类这个空间(类命名空间)中
,而函数则定义在程序所在的空间(全局命名空间)中。
静态方法没有类似 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")