python类加载分析-类属性-实例方法-类方法-静态方法对比

一、 概述
本文对python3的类加载过程进行分析,属于python最核心原理,有下面内容
1、 类对象
2、 实例对象
3、 self变量名称问题
4、 类属性、实例变量、局部变量
5、 类方法
6、 实例方法
7、 类方法与实例方法相互调用
8、 静态方法
9、 继承时三类方法的影响
二、 pytyon类对象
1、 pytyon是脚本语言
pyton的代码在编译时,无论是函数,还是类,都生成了相应的对象,无论这个类是否实例化,都生成了类对象
2、 pytyon类对象是一个静态对象
一旦生成,就不再变化
3、 init构造函数不运行
类对象生成时,init构造函数没有运行
所以调用类方法时,init构造方法的实例属性不存在,不可以调用init方法中self.xxx实例属性
4、 python类对象作用于类方法
@classmethon,类方法的第1个参数是类对象

5、 类属性是类对象的静态变量
即写在类下面,不在任何一个方法中的变量
这类变量可以通过类对象访问,也可以通过类访问,例如
def fun2(cls123):
cls123.n+=2
Test1.n+=2 #与上一行代码作用相同
因为此时,id(cls123)==id(Test1)

6、 类对象与类方法测试示例见后面类方法例

三、 python实例对象
1、 python语言又是面向对象编程
可以实例化,每次实例化时,生成一个实例对象,与类对象没有关系
下面生成3个不同的实例对象
t1=Test1()
t2=Test1()
t3=Test1()
2、 类属性存在二义性
写在类下面的所有变量,既是类对象的静态变量,同时又是每个实例动态变量,有2个不同的内存地址,二者的值在第一次改变前相同,有相同的内存地址,改变后,内存地址不同
见 def fun13(self)示例分析
3、 实例对象时,init构造方法运行
不同于java对象,python没有构造函数重载,可以写多个init,编绎时无语法错误,只有最后一个init方法有效
4、 实例成员访问
任何实例成员,只能通过self.xxx,或self.funxxx(…)访问
任何实例方法中,任何代码块中,无局部变量
5、 实例变量
实例变量self.xxx,可以存在于任何方法中,init构造方法中,任何其他实例方法中,及任何控制语句代码块中,只要这个变量self.xxx运行到了,则这个变量在以后任何地方均有效。

四、 self变量名称问题
1、 每个实例方法的第1个参数是self
2、 可以是任何其他名称
见 def fun12(self123)
self123与self完全相同

五、 类中的变量
1、 类属性有二义性
作用于实例对象的实例方法时,是当前实例动态变量
作用于类对象的类方法时,是静态变量
2、 实例全局变量
self.xxx可存在任何方法中,控制语句代码块中
3、 类方法中的全局变量
与实例变量作用域相同
fun22(self)是类方法,这里用self,只是一个自定义代号,也可以是cls、cls123
self.n2在fun14中有效。
4、 局部变量
实例方法中,不能有局部变量
类方法、静态方法中,可以有局部变量
局部变量仅在当前方法中有效
示例见 def fun22(self)

六、 类方法分析
1、 方法上面有@classmethod
2、 类方法的第1个参数是类对象
可以用类对象调用类方法
可以实例对象调用类方法
还可以从实例方法调用类方法
无论上面三种情况的哪一种, 类方法的第1个参数,永远是类对象,是一个静态对象

3、 类方法可以用类对象直接调用
例如,Test1.fun22() #Test1是一个类对象,编绎到Test1时,生成Test1类对象

4、 类方法也可以通过任何一个实例对象调用
无论是哪一个实例对象访问类方法,类方法的第1个参数永远是类对象,与实例对象无关
5、 类方法地址变化
某一个时刻点,访问类方法时,有相同的方法地址,包括定时N长时间,访问类方法的地址,依然没有变化

再次选中代码运行时,同一个类对象,类方法的地址则发生改变
见示例fun2(cls123)
6、 类方法访问其他类方法
例如def fun22(self)中
self.fun23() #OK
不是self.fun23(self) #语法错误
7、 类方法可访问实例方法
fun22(self)中,self.fun14(self)
fun2(cls123)中,cls123.fun12(cls123)

8、 示例如下


# -*- coding: utf-8 -*-
"""
2018-05-07 14:03:34
作者: 刘明
"""

class Test1():
      n=10
      def __init__(self,n2):
            self.n2=n2
      def fun11(self):
            self.n+=1
            print('self.n=%d,self.n2=%d,self.n3=%d,self.n5=%d'%(self.n,self.n2,self.n3,self.n5))
            print('实-fun1,id(self)=%d,id(self.fun11)=%d,id(self.n)=%d'%(id(self),id(self.fun11),id(self.n)))
            print('self.n=%d,self.n2=%d,self.n3=%d'%(self.n,self.n2,self.n3))
#下面检查实例动态变量可以写在任何实例方法中,不一定要写在__init__中,
      def fun12(self123): #self变量只是一个占位参数,可以是任何变量名称
            self123.n3=3
            #n4=2  #语法错误,实例方法中,不能有局部变量
            if self123.n3==3:
            #  n4=2  #语法错误,实例方法中,不能有局部变量
               self123.n5=5
               pass
            self123.fun11()
            #下面方法检测类变量有2义性,既是静态变量,同时又是实例对的动态变量,在第一次赋值前,两个变量的地址相同,在赋值后,两个变量的地址就发生了改变
      def fun13(self):
            print('1--fun13,id(self.n)=%d,id(Test1.n)=%d'%(id(self.n),id(Test1.n)))
            self.n+=3
            Test1.n+=5
            print('2--fun13,id(self.n)=%d,id(Test1.n)=%d'%(id(self.n),id(Test1.n)))
      def fun14(self2):
            self2.n3=3
            self2.n4=4
            #self2.n2=2 #如果此方法设想为类方法,则self2.n2不是存在的,如果是实例方法,则此变量存在
            #self.n2=2
            #print('n5=%d'%(n5))
            print('self.n=%d,self.n2=%d'%(self2.n,self2.n2))
            #self2.fun11(self2) #本方法只能供类方法调用
            #self2.fun11() #本方法只能供实例方法调用

      @classmethod
      def fun2(cls123):
            cls123.n+=2
            #cls123.fun13()  #语法错误
            #cls123.fun13(cls123) #OK
            cls123.fun14(cls123) #OK
            print('fun2,id(cls123.fun2)=%d,id(cls123)=%d,id(Test1)=%d,id(cls123.n)=%d,id(Test1.n)=%d'%(id(cls123.fun2),id(cls123),id(Test1),id(cls123.n),id(Test1.n)))
            print('fun2,cls123.n=%d,Test1.n=%d'%(cls123.n,Te
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值