今天又重新看了一下js,也看了之前没学的js的面向对象(之前的课缺的太多,这次花了半个小时百度了一点相关知识),突然感觉,js和lua的面向对象挺像的(lua没有对象的概念,只是用table模拟的对象,我说感觉js和lua在这点很像,可能会有很多jsor(自己编的词)会揍我(毕竟我js没看全,可能理解有误)),所以我就尝试python的dict模拟了一下js或lua的面向对象,可能是我受lua的影响,总觉的js的面向对象就是模拟的,不说了,看代码:
首先:说一下我的python方面的理解(个人见解,C语言不咋会,所以可能理解有误):
对于python,所有的变量都是C指针变量,函数也是,这也说明了我们无论存什么数据,其实存的都是指针,可以对比一下Python和C:
先看下Python:
def func(a, b): return a if a>b else b
f = func # ----------------------------------注意对比01
c = f(1, 2) # ----------------------------------注意对比02
print(c) # ==>输出 2
再看C:
void main()
{
int max(int, int);
int (*p)();
int c;
p = max; # ----------------------------------注意对比01
c = (*p)(1, 2); # ----------------------------------注意对比02
printf("%d\n", c); // 输出 2
}
int max(int a, int b) { return a > b ? a : b;}
其实我们从下边也能看出来:
def func(a, b): return a if a>b else b
print(func) # 输出<function func at 0x00000000005FC378>此为函数地址
所以在Python中可以将函数放进字典里边,同时也能调用函数:
def func1(): pass
dic = {"func1": func1}
dic['func']()
PS:其实从这也能看出,闭包也没什么了,原理类似。
那么,我们来用dict模拟一下对象的抽象和封装:
def func1(): return 1
def func2(): return 2
def func3(): return 3
# 下边为对象(类?)的属性添加
dic["a"] = 1
dic["b"] = 2
# print(eval("func1()")) # 此为下边字典生成器的原理
dic = {("func" + str(i)):eval("func" + str(i)) for i in range(1, 4)} # 对象的方法添加
正面我们来输出一下对象dict的属性和方法:
print("a", ": ", dic["a"]) # 属性
print("b", ": ", dic["a"]) # 属性
print("dic.func1()", ": ", dic["func1"]()) # 方法
print("dic.func2()", ": ", dic["func2"]()) # 方法
print("dic.func3()", ": ", dic["func3"]()) # 方法
输出结果分别是:
a : 1
b : 1
dic.func1() : 1
dic.func2() : 2
dic.func3() : 3
也许你会说,对象还有继承和重写呢?
那我们来看看下边的:
首先定义一个function,用来模拟类:
def Classfunc(a, b, c):
dic["a"] = a
dic["b"] = b
dic["c"] = c
def func01(): return 11
def func02(): return 22
def func03(): return 33
dic["func01"] = func01
dic["func02"] = func02
dic["func03"] = func03
return dic # 返回一个字典,这样就能通过函数的返回值模拟创建对象了
类创建好了,现在我们来“创建对象”:cf,并输出cf的“属性”和“方法”
cf = Classfunc("aa", "bb", "cc")
print("a", ": ", cf["a"]) # 属性
print("b", ": ", cf["b"]) # 属性
print("c", ": ", cf["c"]) # 属性
print("cf.func3()", ": ", cf["func01"]()) # 方法
print("cf.func3()", ": ", cf["func02"]()) # 方法
print("cf.func3()", ": ", cf["func03"]()) # 方法
当然,我们也可以得到:
a : aa
b : bb
c : cc
cf.func3() : 11
cf.func3() : 22
cf.func3() : 33
那继承和重写呢?继续看:
上边咱们写了父类ClassFunc了,下边咱们来模拟子类继承父类:
def Classfunc(d, e, sc={}): #sc-->SuperClass父类
dic = {k: v for k, v in sc.items()} # 通过对sc的copy实现继承
dic["d"] = d # 子类添加属性
dic["e"] = e
dic["a"] = "aa_重写" if sc else "aa" # 实现重写 或 增加属性
def refunc01(): return "重写func01"
def func01(): return "增加方法func01"
dic["func01"] = refunc01 if sc else func01 # 实现重写 或 增加方法
def func04(): return 44 # "增加方法func04"
dic["func04"] = func04
return dic
下面我们来分别模拟有继承和无继承的情况:
无继承:
cf1 = Classfunc("dd", "ee") # 无继承
print("a", ": ", cf1["a"]) # 属性 重写了(此时的重写其实是增加属性)
try:
print("b", ": ", cf1["b"]) # 属性b未继承
except Exception as e:
print("属性b不存在")
try:
print("c", ": ", cf1["c"]) # 属性c未继承
except Exception as e:
print("属性c不存在")
print("d", ": ", cf1["d"]) # 属性
print("e", ": ", cf1["e"]) # 属性
print("cf1.func1()", ": ", cf1["func01"]()) # 方法1 重写的
# 由于try之后出现
# During handling of the above exception, another exception occurred:
# 不知道咋回事,就不try了(python没学好)
# print("cf1.func2()", ": ", cf1["func02"]()) # 方法2未继承
# print("cf1.func3()", ": ", cf1["func03"]()) # 方法3未继承
print("cf1.func4()", ": ", cf1["func04"]()) # 方法4 添加的
这时,输出结果是:
a : aa
属性b不存在
属性c不存在
d : dd
e : ee
cf1.func1() : 增加方法11
cf1.func4() : 44
同样,对于有继承的:
cf2 = Classfunc("d", "e", sc=cf) # 有继承
print("a", ": ", cf2["a"]) # 属性 重写了(此时的重写其实是增加属性)
print("b", ": ", cf2["b"]) # 属性b有继承
print("c", ": ", cf2["c"]) # 属性c有继承
print("d", ": ", cf2["d"]) # 属性
print("e", ": ", cf2["e"]) # 属性
print("cf2.func1()", ": ", cf2["func01"]()) # 方法1 重写
print("cf2.func2()", ": ", cf2["func02"]()) # 方法2未继承
print("cf2.func3()", ": ", cf2["func03"]()) # 方法3未继承
print("cf2.func4()", ": ", cf2["func04"]()) # 方法
输出为:
a : aa_重写
b : bb
c : cc
d : d
e : e
cf2.func1() : 重写func 11
cf2.func2() : 22
cf2.func3() : 33
cf2.func4() : 44
其实,通过python对字典的处理(有key时为修改,无key时为添加,和对象类似,js和lua中也是这样),我们就可以用字典(lua中叫table)(模拟类)和函数(模拟类属性和类方法的实现)来模拟出面向对象了。
也许你又双叕会问了,面向对象还有多态呢?方法的重写不就是?其他的几种就别问我了,自己思考吧,我懒得思考了。
刚刚想起来,上边的继承是单继承,如果是多继承,这样就好了:
def Classfunc(d, e, *arg_sc): #sc-->SuperClass
dic = {}
for d in arg_sc: # 先遍历所有父类
for k, v in d.items():
if not dic.has_key(k):
dic[k] = v
# 如果为了速度,用字典生成器则是:
# dic = {k: v for d in arg_sc for k, v in d.items() if not dic.has_key(k)}
在想刚刚这个问题的时候,我对父类有相同方法名的继承问题有疑惑,因此手动测试了一下:
class A(object):
def a(self):
return "a1"
def b1(self):
return "b1"
class B(object):
def a(self):
return "a2"
def b2(self):
return "b2"
class C(A, B):
def c(self):
return "C"
a = A()
b = B()
c = C()
print(a.a()) # ==>输出 a1
print(a.b1()) # ==>输出 b1
print(b.a()) # ==>输出 a2
print(b.b2()) # ==>输出 b2
print()
print(c.a()) # 继承第一个 # ==>输出 a1
print(c.b1()) # ==>输出 b1
print(c.b2()) # ==>输出 b2
print(c.c()) # ==输出 >C
# 通过以上发现,如果子类继承的父类中有相同方法名的方法,则继承第一个继承的
最后,如果大佬们觉得我的理解有错误,请不吝赐教!谢谢!!!