Python 问一个很基础小白的问题,类与函数的关系。RT

married577 · June 24, 2020 · Last by mark replied at June 24, 2020 · 1421 hits

共收到 7 条回复 时间 点赞

因为testArray方法只要求为 self 参数传值,没有规定必须是一个类的对象,所以理论上Hello.testArray()里可以是任何值。

但是如果self 参数传的不是一个类对象,就会引发一个后果:一旦testArray方法使用self参数调用其他类方法,或者简单的用self定义一个实例变量,如self.x = '123',都会导致程序崩溃报错。

这也就失去了用类的意义。

另外,“类名.方法名”的这种调用方式是给静态方法和类方法用的,你这里testArray是一个实例方法,最好用hello.testArray()的方式调用,红框里的用法是一种很别扭的形式。

至于什么是实例方法、类方法、静态方法,搜一下就知道了。

类.方法名字 你红框那个加个new是java调用的方式

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 类方法和实例方法相似,它最少也要包含一个参数,只不过类方法中通常将其命名为 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()
运行结果为:
正在调用类方法
正在调用类方法



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

静态方法没有类似 selfcls 这样的特殊参数,因此 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

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

testArray()是实例方法,python既允许通过实例对象调用实例方法,又允许类名调用实例方法,但是通过类名调用实例方法,要自己为self传参。

如果通过实例对象调用实例方法,python会自动把hello这个对象传给self参数:

hello = Hello();
hello.testArray();

你也可以通过类名调用实例方法,这个时候,你必须为self传参,使用如下:

hello = Hello();
Hello.testArray(hello);

如果你不传参数,就会报错。比如下面的代码直接用类名调用实例方法,但是没有手动给self传参,这样会报错:

Hello.testArray();

但是python没有规定传给self的参数必须是该类的对象,也就是你传一个str给self,也是可以的:

Hello.testArray(str);

像这种通过类名调用实例方法,自己给self传参的调用方式,被称作“非绑定方法”。至于你传一个str进去,但是str不是Hello类的对象,这样会容易出现问题。比如,下面对该类进行一下改造:

class Hello:
x = "in";

def testArray(self, x):
aaa = 'hello, world';
print(x);
print(aaa[0] + "," + self.x);

Hello.testArray(str, "out");

很多时候,我们在方法里面,会利用self调用实例的一些变量和方法,用于区别传进来的参数,但是如果你传给self的是str,str并没有x这个实例变量,那就会报错。

因此,不管是使用类名调用实例方法,还是使用实例调用实例方法,这只是python留给大家的多种选择(或许“非绑定方法”有别的用途),怎么用可能就是习惯的问题了。不过,一般情况下,不该给self传入不是该类对象的参数,因为这样做,程序很容易出现崩溃。

TedZhu 回复

对,其实红框里面的那种调用方式也不好,要写很多多余的代码,大部分人应该都是使用如下的方式:

hello = Hello();
hello.testArray();
  • 你这个代码只能在 Py3 执行
  • The concept of “unbound methods” has been removed from the language. When referencing a method as a class attribute, you now get a plain function object.
    所以 Hello.testArray 是 function, 不是 method

  • 至于上面各位的回答,我感觉是 用py2 强行解释 py3. 如同鸠摩智练六脉神剑

Python 太随意了,这样也不报错

married577 关闭了讨论 29 Jun 13:35
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up