从self、cls看Python的实例化.md

背景

刚开始学习Python的时候经常会有一个疑问,为什么每个类方法的第一个参与一定要加一个self?经过一定的编码后发现,怎么还有一些类方法里面写的是cls

实例化

在使用类方法的时候,我们通常会把一个类做实例化之后再进行调用,比如这样:

class Calc(object):
	def add(self, x, y):
		print x + y


if __name__ == '__main__':
	calc = Calc()
	calc.add(1, 1)

这个self到底是什么呢?我们加两行代码来看。

class Calc(object):
	def add(self, x, y):
		print x + y
		print self


if __name__ == '__main__':
	calc = Calc()
	calc.add(1, 1)
	print calc
	
--->
2
<__main__.Calc object at 0x108b4e4d0>
<__main__.Calc object at 0x108b4e4d0>	

可以看的出来,这个self和实例化出来的calc都是Calc这个对象,并且指向的内存地址是同一个,也就是他们两个是同一个东西。

静态方法

在看别人的代码的时候,经常会看到一个@staticmethod。这个东西是静态方法,在类中的方法都必须要传self对象,但是一旦被@staticmethod装饰器装饰后的方法,就不需要传入self这个参数,如下:

class Calc(object):
	def add(self, x, y):
		print x + y

	@staticmethod
	def minus(x, y):
		print x - y


if __name__ == '__main__':
	calc = Calc()
	calc.add(1, 1)
	Calc.minus(3, 2)

具体来说这个有什么用?我个人理解来说在Python这个装饰器只是一个基于类设计的一个方法。你用一个def来实现,或者就用类方法来实现影响其实并不大。当然,你实例化了,也是可以通过实例来调用静态方法的。

类方法

Python中还有一个方法@classmethod,使用了这个方法,传入的第一个参数就不是self,而是cls。比如这样:

class Calc(object):
	def add(self, x, y):
		print x + y

	@staticmethod
	def minus(x, y):
		print x - y

	@classmethod
	def multi(cls, x, y):
		print x * y


if __name__ == '__main__':
	calc = Calc()
	calc.add(1, 1)
	Calc.minus(3, 2)
	calc.multi(2, 2)
	
--->

2
1
4	

可以在这行代码中吧这个cls打出来看看是个什么东西,最为对比,同样也加上打印self

<class '__main__.Calc'>
<__main__.Calc object at 0x1033ef4d0>

这样对比出来就非常清晰了。cls指的是这个类,如果严谨一点可以再加上print Calc。而self是这个类的一个实例,是放在内存中的。

那么这个到底有什么用呢?说实话,一般来说没什么卵用,跟@staticmethod一样。可以在不需要实例化的时候调用这个方法。

划重点

如果你需要经常对函数的结构进行修改,那么这个方法就非常有用了。

英文好的可以看这里Meaning of @classmethod and @staticmethod for beginner?

英文不好的就看这里Python 中的 classmethod 和 staticmethod 有什么具体用途? - 水中柳影的回答 - 知乎

实例化的过程

理解了selfcls是什么时候,可以继续再研究实例化的过程。

Python在实例化的过程中,会首先调用__new__这个内置的方法。如果我们重写这个方法,但是不按照原有的方式去写,那么就会实例化失败,比如这样:

class Calc(object):
	def __init__(self):
		print "class init..."

	def __new__(cls, *args, **kwargs):
		print "new a class..."

	def add(self, x, y):
		print x + y


if __name__ == '__main__':
	calc = Calc()
	print calc
	
--->
new a class...
None

可以看到,实例化了一个None出来。
__new__方法总增加return object.__new__(cls)即可正常实例化。同时可以看到__init__方法也被执行了。

特别说明一下,这个objectPython所有的新式类的基类。

单例

了解了这些内容,重新来看看单例模式。之前介绍了一个不严谨的单例,这里来看一个比较严谨的单例示例。

class Single(object):
	def __new__(cls, *args, **kwargs):
		if not hasattr(cls, '_single'):
			cls._single = object.__new__(cls, *args, **kwargs)
		return cls._single

这里可以看到在__new__方法中加了一个判断,如果类实例化的时候没有_single这个属性,说明类还没有被实例化,这个时候就按照正常的方法实例化,如果发现有_single这个属性了,那么就直接返回类的_single对象,也就是已经被实例化的对象,通过这个逻辑来保证实例化的时候,只会存在一个实例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点点寒彬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值