Python进阶到高级:类和对象的理解

1、鸭子类型

“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。” 这是百科上对它的解释。

鸭子类型(duck typing)是动态类型的一种风格,鸭子类型对于 Python 编码来讲非常重要,理解它能让你真正理解什么是一切皆对象,更有助于我们理解这门语言的设计思想和实现原理,而不是仅仅浮于表面的念经 “一切皆对象”。

鸭子类型始终贯穿于 Python 代码当中,一个对象它是什么类型取决于它实现了什么协议,因此可以说 Python 是一种基于协议的编程语言。

那这些协议是什么,又有哪些协议?这里的协议,更多的时候我们称为魔法函数或魔法方法,因为它具有很多神奇的魔力,坊间因此称之为魔法函数。

在 Python 里面,所有以双下划线开头,且以双下划线结尾的函数都是魔法函数,就像 __init__ 这种,它们是 Python 语言天然自带的,不是通过某个类去继承而来的,我们也不要随意去自定义一个这样的函数,小心着魔。

魔法函数有很多,但是经常用到的也没多少,常用的一些魔法函数在后面的内容会逐步介绍到。

2、类型判断

在判断数据类型的时候常见的有两种方法:isinstancetype

isinstance("123", str)  # 返回布尔值
type("123")  # 直接返回类型

isinstance 主要用于判断对象的类型。这个好理解,不多讲。

type 可以查看类型,但它能做的远不止于此,它主要用于动态的创建类。

t = type("Mikigo", (), {"name": "huangmingqiang"})
T = t()
print(t)
print(T.name)
print(type(t))

huangmingqiang

你看,我们定义了一个类并赋值给 t,类名为 Mikigo,t 是类对象的引用,name 是其中的属性,Python 中一切都是对象,类也是对象,只不过是一种特殊的对象,是 type 的对象。

这个地方有点绕哈,你细品。

我看到网上好多讲 type 函数,准确讲 type 是一个类,只是用法像函数。在源码中:(通过 Pycharm 按住 Ctrl 点击进入)

class type(object):

    def __init__(cls, what, bases=None, dict=None): # known special case of type.__init__
        """
        type(object_or_name, bases, dict)
        type(object) -> the object's type
        type(name, bases, dict) -> a new type
        1. (copied from class doc)
        """
        pass

有同学要问了,为什么源码里面有 pass,你没看错,源码里面就是写的 pass,这种实际上是由于底层是由 C 语言实现的(本文内容都是基于 CPython),一般的操作是看不到源码的,之所以能看到是因为 Pycharm 给我们提供的功能(其他编辑器不知道哈,没咋用过其他的),相当于以代码的形式看文档,所以我们看到的不是真正的源码,但是最接近于源码的源码,姑且称之为源码吧。

type 的参数说明:

  • 当 type() 只有一个参数时,其作用就是返回变量或对象的类型。
  • 当 type() 有三个参数时,其作用就是创建类对象:
    • 参数 1:what 表示类名称,字符串类型;
    • 参数 2:bases 表示继承对象(父类),元组类型,单元素使用逗号;
    • 参数 3:dict 表示属性,这里可以填写类属性、类方式、静态方法,采用字典格式,key 为属性名,value 为属性值。
@staticmethod
def my_static():
    print("this is static")

t = type("Mikigo", (), {"name": "huangmingqiang", "static": my_static})
T = t()
t.static()
T.static()
this is static
this is static

这样就添加了一个静态方法,很清楚哈,关于静态方法是什么我们后面会讲到,这里只需要知道 type 创建类的方法就好了。