Python类变量 实例变量总结及示例

ref:
http://c.biancheng.net/view/2283.html
https://www.cnblogs.com/crazyrunning/p/6945183.html
https://cloud.tencent.com/developer/article/1527548

学过C++ 或java等强类型,编译型语言,再去学Python类设计时感觉非常不适应,因为Python是在太自由了,让人无所适从,来Python定义类变量、实例对象变量的定义方式、作用域、访问方法的不同吧。

Python变量的本质:被赋值
1 普通python变量(非类相关变量)很容易理解,在被赋值后即变量存在,可读可写
2 Python类的变量(类变量和实例对象变量)以某种方式在某地方被赋值,即存在,可被读写

    Python类变量被赋值
    (1)类的设计里,
    class里def外,通过变量名能被赋值
    def里通过类对象即类名字的点运算变量名可被赋值
    (2)程序里
    通过类对象(类名字)的点运算类名字也可被赋值
    Python实例对象变量被赋值
    (1)类的设计时
    def里通过self点运算变量名能被赋值,不一定非在init里,其他已被调用的方法函数里也行
    (2)程序里
    通过实例对象的点运算变量名可被赋值

类变量和实例变量的区别在于:类变量是所有对象共有,其中一个对象将它值改变,其他对象得到的就是改变后的结果;而实例变量则属对象私有,某一个对象将其值改变,不影响其他对象

在类体中,根据变量定义的位置不同,以及定义的方式不同,类属性又可细分为以下 3 种类型:

    类体中、所有函数之外:此范围定义的变量,称为类属性或类变量;
    类体中,所以函数内部:以“self.变量名”的方式定义的变量,称为实例属性或实例变量;
    类体中,所有函数内部:以“变量名=变量值”的方式定义的变量,称为局部变量。


类变量(类属性)

类变量指的是在类中,但在各个类方法外定义的变量。
 类变量的特点是,在类的所有实例之间共享的变量,也就是说,类变量在所有实例化对象中是作为公用资源存在的,不是单独分配给每个实例的。类方法的调用方式有 2 种,既可以使用类名直接调用,也可以使用类的实例化对象调用。
  注意,因为类变量为所有实例化对象共有,通过类名修改类变量的值,会影响所有的实例化对象。
  python独特的动态语言的灵活性,还可以随时随地动态地为类和对象添加类变量。

实例变量(实例属性)

实例变量指的是在任意类方法内部,以“self.变量名”的方式定义的变量,其特点是实例化之后,每个实例单独拥有一份的变量,只作用于调用方法的对象。另外,实例变量只能通过对象名访问,无法通过类名访问。
通过类对象访问类变量(instance.__class__.value),通过类对象修改类变量的值 (instance.value)很可能是定义新的实例变量。
Python还支持为特定的实例对象添加实例变量,在类体外,运行的时候。这种场景新增的特定的实例变量只对该特定实例对象生效,其他实例对象不受影响。

局部变量

除了实例变量,类方法中还可以定义局部变量,注意局部变量只存在于def内,在def内定义的不带self的变量。和前者不同,局部变量直接以“变量名=值”的方式进行定义,例如:

    class CLanguage :
        # 下面定义了一个say实例方法
        def count(self,money):
            sale = 0.8*money
            print("优惠后的价格为:",sale)
    clang = CLanguage()
    clang.count(100)

通常情况下,定义局部变量是为了所在类方法功能的实现。需要注意的一点是,局部变量只能用于所在函数中,函数执行完成后,局部变量也会被销毁。

class student():
    age = 0   # 注意这里class内函数外的age/name:python语言跟其他语言不同的是,这里定义的是类变量,而其他语言定义的是实例变量
    name = 'stu'
    # age,name是类变量
    def __init__(self,age,name):
        self.age = age
        self.name = name
    # 访问实例变量(用self.age  self.name)

student1 = student(18,'hello')
print(student1.name)
# 打印实例变量,输出hello
print(student.name)  
# 打印类变量,输出stu

In [2]: class Student():
   ...:     name = "张三"
   ...:     age = 0
   ...:     def __init__(self, name, age):
   ...:         name = name
   ...:         age = age
   ...:         

In [3]: student = Student("李四", 19)

In [4]: student.name
Out[4]: '张三'

In [5]: Student.name
Out[5]: '张三'


是实例变量和类变量的区别问题。

我们接着看看对象student的变量有哪些:
In [6]: student.__dict__
Out[6]: {}

为空!

为什么为空呢?(暂时思考下)
我们再看看类Student的变量:
In [7]: Student.__dict__
Out[7]:
mappingproxy({'__dict__': <attribute '__dict__' of 'Student' objects>,
              '__doc__': None,
              '__init__': <function __main__.Student.__init__>,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'Student' objects>,
              'age': 0,
              'name': '张三'})

这里我们要说一下实例变量的查找机制:
当在实例变量中查找不到某一变量时候,就会去类变量里查找,当再查找不到的时候就会在父类中查找,因此输出的name为张三。
之所以为空,是因为我们实例化对象的时候为指明实例变量的保存。现在修改一下实例化函数。


In [10]: class Student():
    ...:     name = "张三"
    ...:     age = 0
    ...:     def __init__(self, name, age):
    ...:         self.name = name
    ...:         self.age = age
    ...:         
    ...:         
    ...:         

In [11]: student = Student("李四", 19)

In [12]: student.name
Out[12]: '李四'

In [13]: Student.name
Out[13]: '张三'

我们传入的self只和实例化的对象有关和类无关,代表实例。
如何在实例方法中调用类变量呢?
 

In [14]: class Student():
    ...:     name = "张三"
    ...:     age = 0
    ...:     sums = 123
    ...:     def __init__(self, name, age):
    ...:         self.name = name
    ...:         self.age = age
    ...:         print(Student.sums)
    ...:         print(self.__class__.sums)
    ...:         
    ...:         
    ...:         
    ...:         

In [15]: student = Student('李四', 19)
123
123

class Person():
    person = 'alive' #这是类变量
    def __init__(self,name ,age):
        self.name = name #这是实例变量
        self.age = age   #这是实例变量
        self.gender = '男' #这是实例变量
        #a = 456     # 这种写法a是def内的局部变量,不是类属性,不是实例属性,类外引用都会报错
    place = ['地球','中国'] #这是类变量

# 若要在def内定义类属性,只有两种方式,如下:
>>> class Person():
    person = 'alive' #这是类变量
    def __init__(self,name ,age):
        self.name = name #这是实例变量
        self.age = age   #这是实例变量
        self.gender = '男' #这是实例变量
        Person.a = 456     #不能写这里,会出错
        self.__class__.b = 'hello'

        
>>> p1 = Person('wa', 18)
>>>
>>> p1.b
'hello'
>>> p1.a
456
>>> Person.a
456
>>> Person.b
'hello'
>>>
class aa:
    w = 10

    def __init__(self):
        self.x = 11
        self.y = 12

    def add(self):
        return self.x + self.y


a = aa()
print (a.add())  //输出23

# 下边两条指令各起何作用?结果是输出两个 20 么?还是两个13?还是?
aa.w = 20  # 修改类变量w值
a.w = 13  # 新增实例变量w
print (aa.w, a.w)  //输出20 13,注意:原因是当类变量与实例变量同名时,实例方式访问时会优先访问实例变量

# 程序继续增加如下,怎样理解这t和q呢?他们是实例变量
a.t = 14
a.q = 15
print (a.t, a.q)  //输出14 15

# 程序继续增加如下,怎样理解这m和n呢?他们是类变量
aa.m = 30
aa.n = 40
print (aa.m, aa.n)  //输出30 40

# 好了再来个提升吧
# 程序继续增加,下列三个print语句都能正确执行么?为何?
b = aa()
print (b.x, b.y)  //正确输出11 12
print (b.t, b.q) //出错,因为不是一个实例了
print (b.m, b.n) //正确输出30 40


实例变量(静态属性)【实例名.实例变量名】

1、实例变量是构造函数下的变量带self.变量

2、实例变量为每个实例本身独有,不可相互调用、新增、修改、删除,不可被类调用、新增、修改、删除

3、可以访问类变量

4、如果同时有类变量和实例变量,程序执行时,先访问实例变量,实例变量存在,会使用实例变量,实例变量不存在,会使用类变量

5、实例改类变量,不可修改,实际是在实例内存里创建了实例变量

6、新增、修改、删除实例变量n,不会影响到类变量n

7、a实例不能调用b实例的变量

8、实例变量可修改、新增、删除

类变量【类名.类变量名】

1、类变量在class内,但不在class的方法内,存在类的内存里

2、类变量是该类所有实例共享的变量,但是实例对象只能访问,不可修改,每个实例对象去访问同一个类变量都将得到相同结果【实例名.类变量名】

3、新增、修改、删除类变量n,不会影响到实例变量n

4、类无权访问实例名

5、类变量可修改、新增、删除
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值