Python中instanceMethod, classMethod, staticMethod区别和使用。类class中的函数中的函数/内嵌函数。类属性初始化时间。

1. 在Python中定义一个Class,通常用到的是普通的instanceMethod。定义instanceMethod时候,第一个参数必须是self,就是instance本身。调用的时候不用手动传入这个参数。classMethod第一个参数必须是cls,就是Class本身。staticMethod不需要(不能用)特殊参数。这里self和cls是convention,你也可以用任何名字,但这个位置会被解释器自动传入instance和class。定义classMethod和staticMethod时候,要在def的上一行用decorator来装饰一下,不加decorator会被当做普通instanceMethod,第一个参数被传入instance。

这几种method都无法直接读取class里的变量/属性,必须要加上类的名字。

class A():
    z = 1
    def im(self):
        print('inst', z)

    @classmethod
    def cm(cls):
        print('cls', z)

    @staticmethod
    def sm():
        print('stat', z)


A.im('self')
# -=> NameError: name 'z' is not defined
# 从class来调用im,没有对应的instance,要手动传入。
A.cm()
# -=> NameError: name 'z' is not defined
# 与im不同,这是classMethod。如果cm传入参数,会报错说传入了2个参数,因为A就是classObject。
A.sm()
# -=> NameError: name 'z' is not defined

a = A()  # 实例化A
a.im()
# -=> NameError: name 'z' is not defined
a.cm()
# -=> NameError: name 'z' is not defined
# cls仍然自动传入
a.sm()
# -=> NameError: name 'z' is not defined

如果把print里的z都改为A.z,那就都能正常运行了。这几种method区别呢?从下面代码可以看出,区别只在于传参方式不同,导致方法内可访问的对象不同,self可访问到当前instance,cls可访问到当前class。然而,当且仅当 知道class的名字,和 将来 instance名字,任何method都还是可以通过名字访问到。实例和类的同名属性,在实例里重新赋值之后,就变成了实例属性,不再受类属性的值影响。

在程序运行当中,instance可以通过type(instance).__name__或者instance.__class__.__name__来获取自己的class名字。class无法获取instance名字。staticMethod也无法获取instance和class名字。只有编程阶段,作者可以知道。

所以,这3种函数的区别只在于decorator导致的传入的参数不同,限制了使用的方式。并没有本质不同。

class A():
    z = 1
    def im(self):
        print('inst', self.z)
        self.z = 3
        print('inst', self.z, '\n')

    @classmethod
    def cm(cls):
        print('cls', cls.z)
        cls.z = 4
        print('cls', cls.z, '\n')

    @staticmethod
    def sm():
        print('stat', a.z)
        print('stat', A.z)
        a.z = 2
        A.z = 6
        print('stat', a.z)
        print('stat', A.z, '\n')

a = A()
a.im()
a.cm()
a.sm()
a.cm()
a.im()

"""
运行结果:
inst 1
inst 3 

cls 1
cls 4 

stat 3
stat 4
stat 2
stat 6 

cls 6
cls 4 

inst 2
inst 3
"""


A.im(a)
A.cm()
A.sm()
A.cm()
A.im(a)
# 结果和上面一样

2. 类class中的内嵌函数(self的变量传递):

普通的不在class里的函数中的函数是不可以直接访问的,只能外层函数内部自用。

实例instance中的变量用self.var表示,需要访问实例 变量和函数 的函数在def的时候要显式声明self参数

def fun(self):

那函数中的函数呢?

class MyClass():
    a = 1
    def fun(self):
        self.b = 2
        def func():
            print(self.b)


mc = MyClass()

print(mc.a)
# -=> 1

mc.fun()
print(mc.b)
# -=> 2

# 到这里一切正常

mc.fun.func()
# -=> AttributeError: 'function' object has no attribute 'func'
# 不能直接访问函数中的函数,不论func()括号中加不加self
# 这点和普通的函数中的函数相同

把class稍加改动,看一下fun能不能访问func,还有func在不加self时,能否读写self.a,self.b

class MyClass():
    a = 1
    def fun(self):
        self.b = 2
        def func():
            print(self.a)
            print(self.b)
            self.a = 3
            self.b = 4
            self.c = self.a + self.b
            print(self.a)
            print(self.b)
            print(self.c)
        func()


mc = MyClass()
mc.fun()
print(mc.a)
print(mc.b)
print(mc.c)

"""
运行结果:
1
2
3
4
7
3
4
7
"""

也就是说,外层函数可以访问自己的内层函数,而且,self.var在整个内外层函数中通用,可以读写;相当于self.var是整个实例instance里的全局global变量。

嵌套函数,内部函数可以访问外部函数定义的变量,但无法修改,如要修改,加nonlocal关键字。


如果想要访问函数中的函数,一般只能靠外层函数返回return一个内层函数出来。

想实现一层一层".访问",其实是返回的实例,不是内嵌函数。比如下面的例子:

class MyClass():
    b = 1
    def fun(self):
        self.b = 2
        print(self.b)

class MyClass2():
    a = MyClass()

mc = MyClass2()
print(mc.a.b)
mc.a.fun()
print(mc.a.b)


3. 类class属性在文件读取的时候就已经初始化了,貌似方法并不会(反正没啥可初始化的)。不会等到实例化__init__的时候。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值