Python番外篇:万法归一,一切皆对象

avatar
作者
猴君
阅读量:2

目录

Python中的对象

一切皆对象

数字是对象

字符串是对象

内置类型也是对象

函数和类也是对象

总结


Python中的对象

对象是Python对数据的抽象,在Python程序中,所有的数据,都可以由对象或对象之间的关系表示。
从某种意义上说,根据冯·诺依曼的“存储程序”的模型,代码也由对象表示。

在Python中,每个对象都有3个核心部分:
1)身份/标识(identity):对象的身份标识一旦被创建,在整个对象的生命周期都是不会改变的,CPyhon中将对象在内存中的存储地址,作为对象的身份标识。
前面已经用到过,使用id()函数可以返回一个表示对象身份标识的整数。

2)类型(type):对象的类型决定了该对象能够支持的运算、操作,以及该对象的取值范围。如同对象的身份标识一样,对象的类型在对象的整个生命周期中也是不可改变的。
通过type()函数可以返回一个对象的类型(它本身也是一个对象)。

3)值(value):某些对象的值可能会发生变化。值可以变的对象被称为是可变对象;而一旦创建后,其值就不可更改的对象称为不可变对象。
需要注意的是,我们知道数字、字符串、元组是不可变对象。但是,对象的不可变性是很微妙的,对象的不可变性与具有不可改变的值,并不是等价的。比如,元组中存储了可变对象的引用,则其元素是可更改的,但是元组对象本身仍然是不可变的对象。

从一切都是对象的角度来看,所谓的容器对象,其实是这些对象的值一般是其他对象的引用。

此外,如同前面的文章中已然提到过的:对于不可变类型,计算新值的操作,实际上可能返回对具有相同类型和值的任何现有对象的引用。而,对于不可变对象,这种操作则是不允许的。

# a和b,可能会,也可能不会引用值为1的同一个对象 a = 1 b = 1  # c和d,一定会引用两个不同的、新创建的空列表对象 c = [] d = []  

输出结果:

一切皆对象

不同于静态类型的编程语言,Python中的面向对象更加彻底,可以说一切皆对象。
前面已经提到,对象的3个核心组成:身份标识(id)、类型(type)、值。其中,通过函数type()我们可以看到对象的类型,也就是用于实例化这个对象的类。
接下里,我们通过对各种实体调用type()函数,来验证Python中一切皆对象。

数字是对象
a = 20 b = int.__int__(20) print(f"对象a,id: {id(a)}, type:{type(a)}") print(f"对象b,id: {id(b)}, type:{type(b)}") 

对象可以有自己的属性和方法:

a = 20 b = int.__int__(20) print(f"对象a,id: {id(a)}, type:{type(a)}") print(f"对象b,id: {id(b)}, type:{type(b)}")  # 数字的实部属性 print(a.real) # 数字的虚部属性 print(a.imag) # 方法bit_count()返回对象的二进制为1的个数 print(a.bit_count())  
字符串是对象
s1 = 'Hello' s2 = str.__str__('Hello') print(s2) print(f"对象s1,id: {id(s1)}, type:{type(s1)}") print(f"对象s2,id: {id(s2)}, type:{type(s2)}") print(s1.upper())  
内置类型也是对象
a = int b = str print(f"对象a,id: {id(a)}, type:{type(a)}, value: {a}") print(f"对象b,id: {id(b)}, type:{type(b)}, value: {b}")  

可以看到,内置类型int,也是对象,这个对象的类型是type,也有自己的id;内置类型str也是类似的。

函数和类也是对象
def say_hello():     print('hello')  class MyClass:     def __init__(self):         pass  print(f"对象say_hello,id: {id(say_hello)}, type:{type(say_hello)}, value: {say_hello}") print(f"对象MyClass,id: {id(MyClass)}, type:{type(MyClass)}, value: {MyClass}")  

输出结果:


函数对象和类对象,也有对应的属性和方法:

def say_hello():     print('hello')   class MyClass:     def __init__(self):         print(f"__init__ was called")   print(f"对象say_hello,id: {id(say_hello)}, type:{type(say_hello)}, value: {say_hello}") print(f"对象MyClass,id: {id(MyClass)}, type:{type(MyClass)}, value: {MyClass}") print(say_hello.__name__) print(say_hello.__code__) say_hello.__call__() print(MyClass.__bases__) MyClass.__init__(MyClass) 

输出结果:


可以看到,函数的__code__属性是一个code对象,也就是开篇提到的代码对象……


简单延伸一下:
Python中,代码对象和函数对象之间的区别在于,函数对象包含对函数全局变量(定义它的模块)的显式引用,而代码对象不包含上下文;默认参数值也存储在函数对象中,而不是代码对象中(因为它们表示在运行时计算的值)。与函数对象不同,代码对象是不可变的,并且不包含对可变对象的引用(直接或间接)。

总结

从上面示例代码中可以看出,内置类型int、str,以及自定义的类MyClass,这些类对象,都是由type这个类对象进行实例化的。那么type这个类对象又是谁实例化的呢?

print(type(int)) print(type(str)) print(type(MyClass)) print(type(type)) 


你没有看错,type类对象是由自己实例化的……

虽然,本文的内容有点绕,但是,必须说的是,Python中的“一切皆对象”的理念,使得Python具有高度的灵活性和一致性。无论是简单的数据类型还是复杂的函数和类,它们都是对象,并可以进行统一的操作。这种设计哲学使得Python代码更加简洁、优雅和易于维护。

当更多地将Python应用于实际场景之后,应该会有更深刻的体会。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!