Python语言特性:类的布局

类与对象

对象是类的实例化,当对象创建后,该对象的内存布局如何,不同的布局将影响对象的方法和属性的调用顺序。通过不同的调用顺序我们也能够看出各种语言背后的实现机制。

C++对象布局

静态语言C++中没有元类这一概念,对象创建后将继承该类的所有属性和方法。当涉及到虚函数的情况下,该类会产生一张虚表,用于决定调用的函数,继承情形下,编译器将修改虚表中函数地址。编译期间,编译器并不知道函数是来自基类或父类,只有在运行期间才知道具体的函数地址。一个类的虚表数量由基类的个数决定,子类的虚表将用于决定对象的调用顺序。

测试示例如下:

class A {

public:

virtual void f1()

virtual ~A()

};

class B {

public:

void f1()

virtual void f2()

~B()

};

class C:public A,public B{

public:

void f1()

virtual void f2()

~C()

};

intmain(void)

{

C c;

return 0;

}

类C(对象c)形成的虚表内存布局如下:

(gdb) p c

$1 ={ = , = {

_vptr.B = 0x40b640 },

类C的布局如下:

2. Python对象布局

Python为动态语言,对象可随时定义新的方法而不受类的限制。一个对象除继承类的方法外,自身还可以定义新的方法来覆盖原类方法;类和对象各有自身的元表用于保存各自的方法和属性,当对象出现自身元表查找失败后,就会查找类的元表来获取对应的属性和方法。

>>>class A:pass

...

>>>a = A()

>>>a.show = lambda x:print(x)

>>>a.show("hello,world")

hello,world

>>> a.__dict__

{'show': at 0x00000000003ECBF8>}

>>>A.__dict__

mappingproxy({'__weakref__':, '__dict__

':, '__doc__': None, '__module__':'__main

__'})

>>>A.s = lambda x:print("A:%s" % (x))

Traceback(most recent call last):

File "", line 1, in

TypeError:() takes 1 positional argument but 2 were given

>>>A.f = lambda self,x:print("A::f %s" % (x))

A::f 1

A:1

>>> A.f(a,1)//self参数本质上指向对应的对象

A::f1

这样对象a的布局图如下:

3. Lua对象布局

C++中类基于虚表来管理多重继承的函数,python中对象基于表的方式来管理类的函数和自身的函数,在Lua中我觉得管理的方式更加趋于继承的本质。Lua中无类的概念,类的实现采用函数来模拟。

一个类主要包含两部分:属性和方法,多重继承本质上用于确定属性和方法;对象创建时调用方法,OO语言则隐藏了this/self参数用于查找方法中的属性值。在lua中,表用于保存属性和方法,这样一个基本类就产生了。

Account ={

balance = 0,

withdraw = function(self,v)

self.balance = self.balance - v

end

}

functionAccount: deposit (v)

self.balance = self.balance

end

local mt=

functionAccount:new(o)

o = o or {}

setmetatable(o,mt)

return o

end

a =Account.new()

a:deposit(100)

print(a.balance)

元表采用lua中表结构形式,分号(Account:deposit)用于暗示该函数隐藏了self参数,a:deposit->getmetatable(a).__index.deposit(a,100)->Account.deposit(a,100)。封装、继承功能则通过修改查找元表函数实现。

function newAccount(balance1)

local self = {

balance = balance1

}

local withdraw = function(v)

self.balance = self.balance - v

end

local deposit = function(v)

self.balance = self.balance + v

end

local getBalance = function ()

return self.balance

end

return {

withdraw = withdraw,

deposit = deposit,

getBalance = getBalance

}

end

a =newAccount(0)

a.deposit(100)

print(a.getBalance())

闭包与类

从Lua的示例可以看出,Lua通过闭包来模拟类、对象。闭包的本质为一个环境,其主要为一个包含函数和变量的环境,类在一定程度上也是这种环境,如果对闭包中的函数定义加以访问限制,一个闭包就等价于一个类。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180612G1RKKQ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券