从self、cls看Python的实例化

背景

刚开始学习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对象,也就是已经被实例化的对象,通过这个逻辑来保证实例化的时候,只会存在一个实例。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容