设为首页 加入收藏

TOP

Python面向对象:杂七杂八的知识点(一)
2019-01-16 14:08:44 】 浏览:378
Tags:Python 面向 对象 杂七杂八 知识点

为什么有这篇"杂项"文章

实在是因为python中对象方面的内容太多、太乱、太杂,在写相关文章时比我所学过的几种语言都更让人"糟心",很多内容似独立内容、又似相关内容,放这也可、放那也可、放这也不好、放那也不好。

所以,用一篇单独的文章来收集那些在我其它文章中不好归类的知识点,而且会随时更新。

class、type、object的关系

python 3.x中,类就是类型,类型就是类,它们变得完全等价。

要理解class、type、object的关系,只需几句话:

  1. object是所有类的祖先类,包括type类也继承自object
  2. 所有class自身也是对象,所有类/类型都是type的实例对象,包括object和type自身都是type的实例对象

论证略,网上一大堆。

鸭子模型(duck typing)

Duck typing的概念来源于的诗句"When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck."。

意思是:如果我看到一只鸟走路像一只鸭子,游泳像一只鸭子,叫起来像一只鸭子,那么我就认为这只鸟是一只鸭子。

在python中,鸭子模型非常容易理解。下面是典型的鸭子模型示例:

class Duck():
    def walk(self):
        print("duck walk")
    def swim(self):
        print("duck swim")
    def quacks(self):
        print("duck quacks")

class Bird():
    def walk(self):
        print("bird walk")
    def swim(self):
        print("bird swim")
    def quacks(self):
        print("bird quacks")

对于Python来说,鸭子模型的意思是:只要某个地方需要调用Duck的walk、swim、quacks方法,就可以让Bird也作为Duck,因为它也实现了这3个方法。

Python并不强制检查类型,只要对象实现了某个所需要的方法,就认为这是可以接受的对象。

它还传达一种思想,A类对象能放在一个地方,如果想让B类对象也可以放在这个地方,只需要让B实现这个地方所需要的方法就可以。

鸭子模型贯穿了python中的运算符重载行为,也贯穿了整个Python的类设计理念。例如print()执行的时候需要调用__str__方法,所以只要实现了__str__方法的类,都可以被print()调用。

绑定方法和非绑定方法

绑定之意,在于方法是否与实例对象(或类名)进行了绑定

当通过实例对象去调用方法时,或者说会自动传递self的方法是绑定方法,其它通过类名调用、手动传递self的方法调用是非绑定方法,在3.x中没有非绑定方法的概念,它直接被当作是普通函数。

例如:

class cls():
    def m1(self):
        print("m1: ", self)
    def m2(arg1):
        print("m2: ", arg1)

当通过cls类的实例对象去调用m1、m2的时候,是绑定方法:

>>> c = cls()
>>> c.m1
<bound method cls.m1 of <__main__.cls object at 0x000001EE2DA75860>>
>>> c.m1()
m1:  <__main__.cls object at 0x000001EE2DA75860>

>>> c.m2
<bound method cls.m2 of <__main__.cls object at 0x000001EE2DA75860>>
>>> c.m2()
m2:  <__main__.cls object at 0x000001EE2DA75860>

也就是说,绑定方法中是绑定了实例对象的,无需手动去传递实例对象。例如:

>>> cc = c.m1
>>> cc()
m1:  <__main__.cls object at 0x000001EE2DA75860>

当通过类名去访问的时候,是普通函数(非绑定方法):

>>> cls.m1
<function cls.m1 at 0x000001EE2DA78620>
>>> cls.m2
<function cls.m2 at 0x000001EE2DA786A8>

>>> cls.m1(c)
m1:  <__main__.cls object at 0x000001EE2DA75860>
>>> cls.m2(c)
m2:  <__main__.cls object at 0x000001EE2DA75860>

唯一需要在意的是,并非一定要通过实例对象去调用方法,通过类方法也能的调用,也能手动传递实例对象。此外,类中的方法并非一定要求有self参数

静态方法和类方法

python的面向对象中有3种类型的方法:普通的实例方法、类方法、静态方法。

  • 普通实例方法:通过self参数传递实例对象自身
  • 类方法:传递的是类名而非对象
  • 静态方法:不通过self传递

从这些方法的简单定义上看,很容易知晓实例方法可以操作类属性、对象属性,而类方法和静态方法只能操作类属性,不能操作对象属性

所以,要实现类方法、静态方法需要合理地定义、传递参数。例如:

class cls():
    def m1(self, arg1):
        print("m1: ", self, arg1)
    def m2(arg1, arg2):
        print("m2: ", arg1)

显然这里m2()是静态方法,m1根据调用方式可以是类方法,也可以是实例方法,甚至是静态方法。例如:

# m1作为实例方法
>>> c.m1("hello")
m1:  <__main__.cls object at 0x000001EE2DA75BA8> hello

# m1作为类方法,通过类名调用,并传递类名作为self参数
>>> cls.m1(cls,"hello")
m1:  <class '__main__.cls'> hello

# m1作为静态方法,通过类名调用,随意处置self参数
>>> cls.m1("asdfas","hello")
m1:  asdfas hello

这样的调用方式并没有什么问题,python是允许这样做的,很自由,但很容易犯错。比如想要通过对象名去调用上面的m2,arg1就必须当作self一

首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Python爬虫入门教程 25-100 知乎.. 下一篇我的Python分析成长之路8

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目