Python面向对象中特殊变量mainname以及关于self的一系列问题

32次阅读

共计 3647 个字符,预计需要花费 10 分钟才能阅读完成。

回过头去敲循环语句的时候,我又碰到了问题:

var = 1
while var == 1:
… num = int(input(“ 输入一个数字:”))
… print(“ 你输入的数字是:“, num)

输入一个数字:4
你输入的数字是:4
输入一个数字:7
你输入的数字是:7
输入一个数字:7.8
Traceback (most recent call last):
File “<stdin>”, line 2, in <module>
ValueError: invalid literal for int() with base 10: ‘7.8’

首先 input 函数永远返回一个 str 类型:

a=input(“input: “)
input: 6
type(a)
<class ‘str’>
b=input(“input: “)
input: 8.9
type(b)
<class ‘str’>

而 Int()函数就很神奇,它可以把一个 str 类型或者一个 number 转换成一个整数:

int(3.4)
3
int(‘100’)
100
int(‘2.3’)
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
ValueError: invalid literal for int() with base 10: ‘2.3’
int(‘air’)
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
ValueError: invalid literal for int() with base 10: ‘air’
int(float(‘2.3’))
2

int()函数应该只能将拥有表面意义的字符串直接转化成整数,也就是说 int 函数是个封装,里面应该是有一个内置函数把 str 转化成 ASCII 或者别的啥我也不知道。
而 int 函数只能把要转化的 string 转化成一个十进制的数,这也就是为什么 air 无法转化成数字:a 对应了 ASCII 中的 97,97 不在 0 - 9 之间,大于 9 的数对 int 来说就是 invalid 的。
为了验证猜想,可以调用 int 函数的另一个功能:

int(12,16)
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
TypeError: int() can’t convert non-string with explicit base
int(’12’,16)
18

只有当输入是一个字符串的时候,他才能把 16 进制的 12 转化成 10 进制的 18。因为 int 函数里只设置了一个内置函数(一个能将字符串转化成 ASCII 码之类的东西再把 ASCII 码转回来的函数)。

然后我开始学习了正则表达式和面向对象, 正则表达式 … 可能因为东西太多了我没啥笔记, 面向对象就还是有一点点的:

class Test:
… def ppr(self):
… print(self)
… print(self.__class__)

t=Test()
t.ppr()
<__main__.Test object at 0x0000019F9A9EA908>
<class ‘__main__.Test’>

挺简单的, 就是 self 指一个实例,ppr 这个方法里面的 print(self)返回了 self 这个实例的地址;self.__class__则返回了一个类, 可以看出 Test 就是那个类.main 应该就是所有东西调用的地方
以__class__,__main__为代表的以双下划线为开头双下划线结尾的特殊变量(可以直接访问的变量)。__class__是什么很好理解,它指向类,在这里应当是 Test 这个类。然而这个__main__在查了 document 之后解释为:the environment where the top-level script is run. The name of the scope in which top-level code executes. A module’s __name__is set equal to “__main__” when read from standard input, a script or from an interactive prompt. 看上去这个__main__的出现似乎之和运行方式有关。
__name__is a built-in variable which evaluates to the name of the current module.
(大型偷懒现场)
https://stackoverflow.com/que…
https://www.geeksforgeeks.org…
https://www.journaldev.com/17…
前两个讲了__main__和以及和__name__的关系,第三个链接讲述 main 函数

感觉今天脑子不转了:

class A(object):
… def f(self):
… return 123

a=A()
print (A.f())
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
TypeError: f() missing 1 required positional argument: ‘self’
print (a.f())
123

第一个 A.f()我以为它是一个类方法,它却返回我缺少位置参数 self,self 在我眼中代表了一个实例,这不是说明我缺少了一个实例作为参数,也就是说这个 A.f()实际是 A.f(self)而这个 self 需要的是一个像 a 一样的实例?
a.f()是一个方法,但要是前面的假设是正确的,那么它其实应该是 A.f(a)
对我看到了这个:

class Test:
… def ppr():
… print(self)

t=Test()
t.ppr()
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
TypeError: ppr() takes 0 positional arguments but 1 was given

也就是说在定义 ppr 的时候没有给 self,而 t.ppr()在内部处理的时候变成了 Test.ppr(t),因为没有定义参数,所以括号里并不应该给一个变量,所以出现了这个提示。
再加上 self:

class Test:
… def ppr(self):
… print(self)

t=Test()
t.ppr()
<__main__.Test object at 0x00000241F67CB848>
t.ppr(3)
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
TypeError: ppr() takes 1 positional argument but 2 were given
t.ppr()=Test.ppr(t),实例地址在 0x00000241F67CB848,嗯很完美
t.ppr(3)=Test.ppr(t,3), 多给了一个变量,所以提示只需要一个但是给了两个。

这是问题的前一半,我留了后一半打算慢慢想,因为我试了各种组合发现如下:

class Test:
… def ppr(self):
… print(self)

t=Test()
Test.ppr
<function Test.ppr at 0x00000241F6792CA8>
t.ppr
<bound method Test.ppr of <__main__.Test object at 0x00000241F67CBA48>>
t.ppr()
<__main__.Test object at 0x00000241F67CBA48>

Test.ppr 显然是一个类方法,但是返回了一个 function,或许 python 中把方法当成了一种特殊函数处理(保留问题)?
t.ppr 和 t.ppr()返回了同一个地址但是前者返回了绑定了实例的方法的的地址,
后者加了括号,返回的是这个方法的结果,即 self 的地址,两个地址是相同的,也没什么问题
再试一个:

class A(object):
… def f(self):
… return 123

A.f
<function A.f at 0x0000027D9CE8C5E8>
A.f()
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
TypeError: f() missing 1 required positional argument: ‘self’
a=A()
a.f
<bound method A.f of <__main__.A object at 0x0000027D9CD9C988>>
a.f()
123

a.f 返回绑定了实例的方法所在地址,a.f()在这里更直观一些返回了方法的结果,也没有问题
那么今天就遗留了一个为什么 A.f 是一个 function 而不是一个 method 的问题。

正文完
 0