首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

06投稿:一切皆Class-个人理解

阅读本文大约需要6.3分钟。

面向对象编程可以说是Python语法体系中最难的了,这个就算我有C的基础也是一点用都没,因为C还没有面向对象的编程思想,第一遍看书时候基本都没看懂,这次再看教程和之前看的turtle库源码,对Class的理解渐渐有了点眉目。

'''首先,我们定义一个类,它就是一个东西的集合,比如人类、学生、动物……括号里的是继承的父类,我们新建的这个类就是它的子集,继承了父类已有方法,但又有自己的独有方法'''

class Student(object):

'''这个类是有一些属性的,比如学生们的身高体重等等,不同的人身高体重是不同的,我们用这些对它们进行区分,以便之后实例化他的时候调用。'''

def__init__(self,name,height=175,weight=50):

self.name=name

self.height=height

self.weight=weight

'''作为一个类,不仅有属性,还有方法,其实就是他们所拥有的能力,比如学生会学习、玩、睡'''

def study(self):

print('{} isstudying'.format(self.name))

def play(self):

print('{} isplaying'.format(self.name))

def sleep(self):

print('zzZ')

'''我们建立几个学生的实例,比如学生小李,学生小王,可以在定义他们时候便输入他们的属性,这样会通过__init__方法给他们的属性赋初值,当然身高体重已经有默认值了,不赋也不会出错'''

li=Student('xiaoli')

wang=Student('xiaowang',172,80)

'''现在,两个活生生的实例便诞生了,我们可以通过.(参数)调用方法,让他们使用自己作为学生所拥有的能力,(因为现在他们只是学生类,只会学生所具备的能力),也可以通过.调出属性'''

li.study()

wang.sleep()

print('his name is{}'.format(li.name))

#大部分注释都用两句话,第一句是刚接触类的感悟,第二句是之后深入理解类时候的想法

好了,现在已经可以写一个简单的class了,但这只是最最基本的class,我们可以通过这个例子看出,这和我们直接使用函数没什么不同嘛,只是每次调用都针对着不同对象,不过仔细想想,不同的对象……这不就是我们操作的数据吗,每一个对象都是一个数据。

那么反过来,哪个数据又不是对象呢?我们的float、int、str、list、dict不都是操作的对象吗,特别是list,很早就见过list.的形式对它进行操作了,这些不都是一样的嘛?

冥冥中他们似乎有着某种联系,难道……有预先设定好叫做list、int、str等等的class?我们使用函数都是调用他们所在class下的方法?后面看到len(str)其实是在调用str.__len__()方法,我就更加确信这一点了,再往后看,我渐渐明白了class的原理,或者说……Python对数据的操作的原理。

首先,我们大概用数学的集合概念表征一下类的关系,我们最大的集合就是object,它有着很多很多的子集,包括int、float、dict、list、tuple、module等等,这些是没有显式定义的class,事实上一定有那么一个地方是定义着这些class的。

除此之外,我们可以显式地定义一些class,就像我之前写的Student,很明显这也是一个object的子集,同时,我们也可以用继承关系创建无数的class,我们可以很容易的从集合的角度理解他们之间的关系(子类继承父类,这就像子集拥有父集的一般属性一样)。

最后就是实例化了,我们可以将它理解为元素,因为它不能再包容其他元素了,所以不能再叫他集合了(不再是class了,他只能属于某个class)。这时候我们把集合全换成class,子集换子类,父集换父类,元素换实例,仔细想一下,是不是就可以理解了呢?

当然我们的子类不能一味地继承父类,子类可以定义自己的方法属性,实例也是一样的。在集合里很容易理解元素与子集之间的关系,实例与子类也是一样的,不严谨的说,实例就是一个最小的子类。正是因为他已经很具体到实例了,所以我们才会对他进行具体的操作,就像我们只会操作0、1、2这样具体的数据,不会操作自然数这样一个泛泛的集合一样。

我们理解class层次关系时完全可以这么想,实例继承了上层父类的所有可继承能力。这里提到了可继承,就是出于之前对__xxx与_xxx的一点疑问,__xxx是只有所在类可以调用,连子类(包括实例)都不能用,而_xxx是所在类及其子类(包括实例)均可调用。

之前提到module也是一个class,有着未显式定义的方法,但是我们为什么可以直接操作turtle这样的库名呢?因为turtle就是一个module类的实例啊!我们保存在module文件里的语句函数都是绑定在该实例上的方法属性!之前有看到实例不可以调用所在类的__xxx方法,这个很容易理解,后来看到了一个库拒绝调用的方法属性是用_xxx就可以,现在再想想,当然会拒绝了,我们写的文件里怎么可能有module实例下的子类呢?实例下已经不可能有子类了呀。

(这里的最底层都是实例,虽然是使用集合形式去理解继承的关系,但由于只在多重继承才会出现与层次图的矛盾,所以只用层次图搭建了一个主框架)

继承关系是自上而下逐层寻找的,而调用方法属性的过程恰恰相反,Python根据实例调用方法或属性的格式,首先在实例绑定的方法属性中找,找不到会接着找上层的类是否有对应属性方法,以此类推,一直找到object(所以大概这里有对最基本的class的定义)。(我认为这些方法属性都只是函数,只不过属性要么就在最开始用__init__函数定义,要么就用装饰器传入值或设置返回值(因为这样可以给属性一个限制))。

这种按照调用格式寻找是指,print(a.age)这样就很自然地就去找a所在class的__init__初始化属性,a.eat()就去找eat()方法,其他的格式会去找特有的方法,比如len(a)会去找__len__方法,for i in a会去找__iter__()和对应的__next__()方法,等等。Python所操作的一切数据都是被实例化的class,因此我们完全可以用class写出对基本数据类型的操作方法。

最后,我想了下我们平时写的代码又是在什么环境呢?我的猜测是一个类似于module的type,因为我们是可以在这里调用module下的方法__name__的,虽然可能是巧合,但我觉得,我们写的代码也不过只是未导入的module而已,事实上,我们写的所有有效文件应该都会被一个一个地import到其他文件中,所以……我认为、这些都是module,而一切、皆class!

‘’’turtle库源码是我对class产生疑问的起点,源码中同时爬的两只小乌龟让我产生了很浓厚的兴趣,但是如何产生两只小乌龟的呢,又是如何同时爬的呢?百度上查到同时爬是多线程的结果,两只小乌龟是我在源码里发现了有两个实例化的过程,但我也因此产生了我们平时为什么可以直接调用.()的疑问,源码中没有找到被实例化为turtle的任何类,这个问题一直困扰着我,就如同即将建成的python大厦上有一小朵令人不安的的乌云(龟),之后我带着疑问问向了Wisink哥,他一语道破我的盲点!

>>>type(turtle)

turtle的type是module,这是一个从未见过的type,我一时慌乱,感觉自己建设了许久的大厦即将崩毁。为了不让建设了很久的“大厦”倾倒,我又苦想了很久,才得出了module和int等完全一样的结论,turtle是它的一个实例,就像123是int的一个实例一样。还好没有放弃,最终总算找到了问题的关键所在。’’’

print(‘Thanks for Wisink!Thanks for turtle.py!’ )

#感谢Wisink哥,感谢小海龟,如果不是你们,我看不到真正的天空!

(April 7

,2018

写在最后:

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180408G003BJ00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券