编程小白 问关于python当中类的方法的参数问题
问题描述
代码如下:
# -*- coding:gb2312 -*-class CarStore(object): def order(self,car_type):return Factory.select(car_type)class Factory(object): def select(car_type): #为什么这个地方的方法,没有self参数也可以运行?if car_type == '索纳塔': return Suonata()elif car_type == '名图': return Mingtu()else: print('没有您要的车型!')class Car(object): def move(self):print('车在移动...') def music(self):print('正在播放音乐...') def stop(self):print('车在停止...')class Suonata(Car): def __init__(self):print('索纳塔')class Mingtu(Car): def __init__(self):print('名图')car_store = CarStore()suonata = car_store.order('索纳塔')#car.move()#car.music()#car.stop()suonata.move()
执行结果:
这段代码本身是没有问题,可以执行的。我的疑问是,为什么第七行代码def select(car_type): 这个地方明明没有self,也可以执行?我记得我在学类的时候,被教育实例方法里面每个方法都必须加上一个self的参数,这里居然没有,然后我在这个地方加上了self反而出错了,如下图:
结果反而运行出错:
为什么会这样?
问题解答
回答1:你是不是用的python3?在python3中,如果成员函数不加self,则代表该函数是静态成员函数,可以直接使用“类名.函数名(参数)”的形式直接调用。但是如果你加了self,则这个函数为类的成员函数,在其他调用类中必须这样调用:“类名.函数名(self,参数)”,或者在调用类类中实现一个实例,“实例名.函数名(参数)。
python3是上述这样,我的测试,在python2中不是。
你在select函数中加了self,但是在 CarStore::order()中调用却使用“类名.函数名(参数)”的形式,所以不正确。你在CarStore::order()调用时改为“类名.函数名(self,参数)”或者在CarStore::order()实现一个实例,使用“实例名.函数名(参数)“这样的形式试试。
昨晚看到的,太晚了,所以今天早上测试的。
回答2:self 不是魔法,改成什么名字都可以的
不一定非要 self
回答3:4 return Factory.select(self, car_type)回答4:
class Factory(object): def select(car_type):if car_type == '索纳塔': return Suonata()elif car_type == '名图': return Mingtu()else: print('没有您要的车型!')
按这个写法,select是对象方法,调用需要关联一个实例Factory()。调用时对象实例是与第一个参数car_type绑定。这个参数名一般约定为self但是,不要求。
你需要明白以下两种调用方式是不同的:
f = Factory()f.select(xxx)Factory.select(xxx)
第一种方式,用实例对象去调用,第一个参数car_type自动与实例对象f绑定;第二种方式,用类去调用,第一个参数(car_type)没有绑定;你需要自己绑定才能不出错——也就是你传进去的car_type:Factory.selct(car_type)这行。
但是,当你加上self后,这个函数有两个参数,但是你只绑定了car_type,也就是绑定到第一个参数self,第二个没有值,必然就出错了。
这里你要做的其实是将select实现成类方法:
class Factory(object): @classmethod def select(cls, car_type):if car_type == '索纳塔': return Suonata()elif car_type == '名图': return Mingtu()else: print('没有您要的车型!')
那么,以Factory.select(car_type)调用时,cls自动绑定到Factory,而car_type则绑定到car_type。
以上,无论是self还是cls,都只是约定的名字而已,起作用的是Python的类-对象-方法模型。
建议可以看看《Python源码剖析》,至少要理解@classmethod是怎么工作的,要不然是写不好这类代码的。
相关文章:
1. docker-compose 为何找不到配置文件?2. 在mac下出现了两个docker环境3. docker images显示的镜像过多,狗眼被亮瞎了,怎么办?4. macos - mac下docker如何设置代理5. 在windows下安装docker Toolbox 启动Docker Quickstart Terminal 失败!6. angular.js - angular内容过长展开收起效果7. PHP中的$this代表当前的类还是方法?8. objective-c - iOS开发支付宝和微信支付完成为什么跳转到了之前开发的一个app?9. dockerfile - [docker build image失败- npm install]10. java - 我用Tomcat访问SQL server数据库时,出现以下错误,该怎么解决?