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

目录

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应用于实际场景之后,应该会有更深刻的体会。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南宫理的日知录

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值