Python学习笔记:有关<Python3学习笔记>学习整理,第2章类型[1]

2.1.1 印象

我们习惯将生物分为动物,植物,进而又有猫科,犬科等细分,通过对个体的研究,归纳其共同特征,抽象成便于描述的种族模版,有了模版后,可据此创建大量行为类似的个体,所以,分类是个基础工程。

在专业术语上,我们将族群或类别乘坐类型(class),将个体叫做实例(instance)。类型持有同族个体的共同行为和共享状态,而实例仅保存私有特性即可。如此,在内存空间布局上才是最高效的。

每个实例都持有所属类型的指针。需要时,通过它间接访问目标即可。但从外在逻辑接口看,任何实例都是“完整”的

存活实例对象都有“唯一”id值:

补充:

id()函数:用于获取对象的内存地址

语法:id([object])

返回值:返回对象的内存地址。

可用type返回实例所属的类型:

要判断实例是否属于特定类型,可以使用isinstance函数

补充:

isinstance()函数:判断一个对象是否是一个已知类型

语法:isinstance(object, classinfo)

参数:

object -- 实例对象。
classinfo -- 可以是直接或间接类名、基本类型或者由它们组成的元组。

返回值:如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False。

isinstance() 与 type() 区别:
type() 不会认为子类是一种父类类型,不考虑继承关系。
isinstance() 会认为子类是一种父类类型,考虑继承关系。
如果要判断两个类型是否相同推荐使用 isinstance()

任何类型都是其祖先类型的子类,同样,对象也可以被判定为其祖先类型的实例

class A:
    pass
class B(A):
    pass
print(issubclass(B,A))

结果:

补充:

issubclass():用于判断参数class是否是类型参数classinfo的子类

语法:issubclass(class, classinfo)

参数:

class -- 类
classinfo -- 类

返回值:如果 class 是 classinfo 的子类返回 True,否则返回 False

注意:所有类型都有一个共同的祖先类型object,它为所有类型提供原始模版,以及系统所需的基本操作方式

class A:
    pass
class B(A):
    pass
print(issubclass(B,object))

结果:

类型虽然是抽象族群概念,但在实现上也只是个普通的对象实例,区别在于,所有类型都是由type创建,这和继承没有关系

单就类型对象而言,其本质就是用存储方法和字段成员的特殊容器,用同一份涉及来实现才是正常思路,当然,类型对象属于创建者这样的特殊存在,默认情况下,它们由解释器在首次载入时自动生成,生命周期与进程相同,且仅有一个实例

2.1.2 名字

在通常认知里,变量是一段具有特定格式的内存,变量名则是内存别名,因为在编码截断,无法确定内存的具体位置,故使用名称符号代替

静态编译和动态解释型语言对于变量名字处理方式的不同点:

静态编译:静态编译器或链接器会以固定地址,或直接、间接寻址指令代替变量名,也就是说,变量名不参与执行过程,可被剔除。

动态解释型语言:名字和变量通常是两个运行期实体。名字不但有自己的类型,还需要分配内存,并介入执行过程。甚至可以说,名字才是动态模型的基础

名字必须要与目标对象关联起来才有意义,最直接的关联操作就是负值,而后对名字的引用都被解释为对目标对象进行操作

赋值步骤:

1.准备好右值目标对象

2.准备好名字

3.在名字空间里为两者建立关联(namespace{名字:目标对象})

即便如此,名字与目标对象也仅是引用关联,名字只负责招人,但对此人一无所知。鉴于在运行期才能知道名字引用的目标类型,所以说Python是一种动态类型语言

名字空间:

名字空间(namespace):是专门用来存储名字和目标引用关联的容器

对Python而言,每个模块(源码文件)都有一个全局名字空间。而根据代码作用域,又有当前名字控件或本地名字空间一说,如果直接在模块级别执行,那么当前名字空间和全局名字空间相同,但在函数内,当前名字空间就专指函数作用域

名字空间默认使用字典数据结构,由多个键值对组成

内置函数globals和locals分别返回全局名字空间和本地名字空间字典

代码1:

y=100
print(id(globals()))
print(id(locals()))
print(globals())
print(locals())

结果1:

30466768
30466768
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000000003A1CC0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Pyexerice/func_lambda1.py', '__cached__': None, 'y': 100}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000000003A1CC0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Pyexerice/func_lambda1.py', '__cached__': None, 'y': 100}

此时globals和locals指向相同,所以内存地址相同,结果相同

代码2:

def test():
    y = 100
    print(id(globals()))
    print(id(locals()))
    print(globals())
    print(locals())
test()

结果2:

30663376
39180904
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001CF1CC0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Pyexerice/func_lambda1.py', '__cached__': None, 'test': <function test at 0x0000000001D2C1E0>}
{'y': 100}

可以看到,此时globals和locals的内存地址不同,由此可见,globals总是指向模块名字空间,而locals则是指向当前作用域环境

未完待续

猜你喜欢

转载自www.cnblogs.com/reseelei-despair/p/11127627.html