Python3之类浅谈(二)

日期:2020年1月25日
作者:Commas
注释:学习就是为了忘记,对Python3类命名空间与作用域来一个小结。
如果您想了解更多有关Python的知识,那么请点《我的Python浅谈系列目录》



在正式讲解本章主题的之前,我们先要对类和类对象进行一个更进一步的了解,首先我们探讨一下类的本质。

一、探索类的本质

程序在解释类的时候,实际上会开辟一块内存空间,将类的相关信息保存到其中,我们不妨先定义一个Chinese类,如下所示:

class Chinese:
    """中国人的类"""

    language = "Mandarin"

    def __init__(self, name, sex="male"):
        self.name = name
        self.sex = sex

    def say_hello(self):
        """中国式打招呼"""
        print("{}:吃了饭没呀?".format(self.name))

接下来我们用id()查询类的十进制内存地址,如果有,那么就说明程序解释到类的时候,会开辟一块内存空间,如下所示:

print("{}的十进制内存地址为:{}".format(Chinese, id(Chinese)))
print("{}的十六进制内存地址为:{}".format(Chinese, hex(id(Chinese))))

# 控制台输出:
<class '__main__.Chinese'>的十进制内存地址为:2980050429240
<class '__main__.Chinese'>的十六进制内存地址为:0x2b5d8d8e538

既然有开辟内存地址,那么我们看看内存空间中,到底保存了点什么信息,
我们先来用用常用的一个内置函数dir()查看一下,如下所示:

print(dir(Chinese))

# 控制台输出:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'language', 'say_hello']

在茫茫词海中,我看到了一个__ dict __,和字典的dictionary有点像,那么这里面储存了什么信息,如下所示:

print(type(Chinese.__dict__))

# 控制台输出:
{
	'__module__': '__main__',
	'__doc__': '中国人的类',
	'language': 'Mandarin',
	'__init__': < function Chinese.__init__ at 0x0000023A1B1198C8 > ,
	'say_hello': < function Chinese.say_hello at 0x0000023A1B119950 > ,
	'__dict__': < attribute '__dict__' of 'Chinese' objects > ,
	'__weakref__': < attribute '__weakref__' of 'Chinese' objects >
}

控制台输出看起来很眼熟啊,这不就是我刚刚定义的Chinese类么?分析如下表:

属性或方法类型说明
__ doc __内置属性Chinese类的说明介绍,中国人的类。
__ init __内置方法类实例化对象的时候,自动调用的第一个方法,动态属性在其方法中定义。
language用户定义的静态属性Chinese类中静态属性language的值为Mandarin(普通话)
say_hello用户定义的方法用户定义的公有方法,中国式打招呼的方法。

看起来很像字典类型(可变类型),实际上是不可变映射类型的“字典”,类型为“mappingproxy”,只允许访问,不允许修改,如下所示:

print(type(Chinese.__dict__))
print(Chinese.__dict__.get("language"))      # 访问类的静态属性language的值
print(Chinese.__dict__["language"])          # 访问类的静态属性language的值
Chinese.__dict__["language"] = "Cantonese"   # 尝试修改类的静态language值,将“普通话”改为“广东话”,但是不可以,并抛出TypeError异常。

# 控制台输出:
<class 'mappingproxy'>
Mandarin
Mandarin
Traceback (most recent call last):
File "D:/test.py", line 4, in <module>
Chinese.__dict__["language"] = "Cantonese"
TypeError: 'mappingproxy' object does not support item assignment

二、探索类对象(实例)的本质

当类对象被实例化出来的时候,就会在内存空间开辟一个空间,我们用内置函数dir()查看一下对象里面有些什么,如下:

# ①实例化
xu = Chinese("老许")
# ②对象的内存地址
print(xu)
print("{}的十六进制内存地址为:{}".format(xu, hex(id(Chinese))))
# ③用内置函数dir()查询对象
print(dir(xu))

# 控制台输出:
<__main__.Chinese object at 0x000002246ED324A8>
<__main__.Chinese object at 0x000002246ED324A8>的十六进制内存地址为:0x2246cff4bf8
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'language', 'name', 'say_hello', 'sex']

实例xu也有属性__ dict __,那么我们看一下这个值的类型以及值,如下所示:

print(type(xu.__dict__))
print(xu.__dict__)

# 控制台输出;
<class 'dict'>
{'name': '老许', 'sex': 'male'}

xu对象和Chinese类的__ dict __不一样,如下表所示:

xu对象Chinese类
__ dict __ 类型可变数据类型的字典不可变映射类型的“字典”
__ dict __仅对象属性(动态属性)类的静态属性以及方法

三、类与类对象的关系浅谈

在这里插入图片描述
如上图所示,类与类对象之间的几个知识点如下:

  1. 对象只保存动态属性(对象的属性),并不储存类中的静态属性和方法;
  2. 对象存在一种指向类的关系,共享类中的资源(静态属性和方法),同时可以节省内存;
  3. 类不存在指向对象的关系,所以在类中,无法访问被自己实例化的对象;
  4. 对象命名空间遵循“就近原则”,即在对象访问变量时,若动态变量有,则访问本对象中的动态变量,否则访问实例化该对象的类的静态属性,若两者皆无,则抛出异常;

版权声明:本文为博主原创文章,如需转载,请给出:
原文链接:https://blog.csdn.net/qq_35844043/article/details/104083837

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值