python中的类属性、实例属性、类方法、实例方法

小结   类方法和类属性既可以通过类名调用,也可以通过实例调用;实例方法只能通过实例调用,实例属性可继承和覆盖(重名时)类属性,通过实例来调用。

1.实例属性每个实例各自拥有,相互独立而类属性有且只有1份,创建的实例都会继承自唯一的类属性。意思就是绑定在一个实例上的属性不会影响到其它的实例。如果在类上绑定一个属性,那么所有的实例都可以访问类属性,且访问的类属性是同一个,一旦类属性改变就会影响到所有的实例。

2.类属性直接绑定在类上的,可以不实例化直接通过类名调用类属性

3.当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。

4.实例方法:在类中定义的函数,第一个参数是self,指向调用该方法的实例本身。调用实例方法必须在实例上调用

5.通过标记一个@classmethod,将方法绑定到类上,而非类的实例上。类方法的第一个参数传入的是类本身cls,上面的cls.count相当于Person.count。因为在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用。

类方法是通过类来直接调用的,或者通过实例直接来调用。

定义类

  1. class Person():

  2. pass

创建实例,一个类可一创建多个实例,每个实例可以有不同的属性

  1. xiaoming = Person()

  2. xiaohong = Person()

实例属性

  1. xiaoming = Person()

  2. xiaoming.name = xiaoming

  3. xiaoming.age = 24

  4. xiaoming.sex = man

  5.  
  6. xiaohong = Person()

  7. xiaohong.name = xiaohong

  8. xiaohong.age = 22

  9. xiaohong.sex = woman

初始化实例属性

当创建实例时,__init__()方法会被自动调用

  1. class Person(object):

  2. def __init__(self, name, age, sex):

  3. self.name = name

  4. self.age = age

  5. self.sex = sex

属性的访问限制

python中定义的普通变量,可以被外部访问。但是有时候,定义的变量不希望被外部访问。

python对属性权限的控制是通过属性名来实现的。如果一个属性由双下划线(__)开头,该属性就无法被外部访问。如果外部需要访问这种变量,可以通过实例方法来访问,在下文将会介绍如何访问。
class Person(object):

  1. def __init__(self, name):

  2. self.name = name

  3. self._title = 'Mr'

  4. self.__job = 'Student'

  5.  

  6. p = Person('Bob')

  7. print p.name # => Bob

  8. print p._title # => Mr

  9. print p.__job

  10. # => Error

  11. Traceback (most recent call last):

  12. File "<stdin>", line 1, in <module>

  13. AttributeError: 'Person' object has no attribute '__job'

属性以"__xxx__"的形式定义的,是可以被外部访问的。它在python中称之为特殊属性。一般都是python内置的属性或者方法,一般我们定义属性和方法时不建议使用这种形式。

类属性

直接在类中创建的属性就叫类属性。

实例属性每个实例各自拥有,相互独立而类属性有且只有1份,创建的实例都会继承自唯一的类属性。意思就是绑定在一个实例上的属性不会影响到其它的实例。如果在类上绑定一个属性,那么所有的实例都可以访问类属性,且访问的类属性是同一个,一旦类属性改变就会影响到所有的实例。

  1. class Person(object):

  2. address = 'Earth' # 类属性address

  3. def __init__(self, name):

  4. self.name = name

  5.  
  6. print Person.address # => Earth 类属性直接绑定在类上的,可以不实例化直接通过类名调用类属性

  7.  
  8. p1 = Person('Bob')

  9. p2 = Person('Alice')

  10. print p1.address # => Earth # 通过实例来调用类属性

  11. print p2.address # => Earth

例:请给 Person 类添加一个类属性 count,每创建一个实例,count 属性就加 1,这样就可以统计出一共创建了多少个 Person 的实例

  1. class Person(object):

  2. count=0

  3. count += 1

  4. def __init__(self, name):

  5. self.name = name

  6.  
  7. p1 = Person('Bob')

  8. print Person.count # 1

  9.  
  10. p2 = Person('Alice')

  11. print Person.count # 1

  12.  
  13. p3 = Person('Tim')

  14. print Person.count # 1

上述代码没有达到想要的效果。

  1. class Person(object):

  2. count=0

  3. def __init__(self, name):

  4. self.name = name

  5. Person.count += 1

  6.  
  7. p1 = Person('Bob')

  8. print Person.count # 1

  9.  
  10. p2 = Person('Alice')

  11. print Person.count # 2

  12.  
  13. p3 = Person('Tim')

  14. print Person.count # 3

__init__理解成是一个构造函数,构造函数外围的count=0理解成是一个默认参数,而在实例化对象的实现最先调用的是构造函数,然后在第一次调用构造函数里面的count因为没有值就是使用默认参数,因此第一次调用的count是0的默认值,然后第二次调用的时候是有参调用以此用的是有参的count。

count=0,是对最初的第一次赋值,只作用一次,往后每个对象都会使用改变后的count。

实例属性和类属性重名

当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。

 
  1. class Person(object):

  2. address = 'zhejiang'

  3. def __init__(self, name):

  4. self.name = name

  5.  
  6. p1 = Person('Bob')

  7. p2 = Person('Alice')

  8.  
  9. print 'Person.address = ' + Person.address # zhejiang

  10.  
  11. p1.address = 'shanxi'

  12. print 'p1.address = ' + p1.address # shanxi

  13.  
  14. print 'Person.address = ' + Person.address # zhejiang

  15. print 'p2.address = ' + p2.address # zhejiang

可见,千万不要在实例上修改类属性,它实际上并没有修改类属性,而是给实例绑定了一个实例属性。

定义实例方法

使用场景:一个实例的私有属性通过“__属性名”来定义,无法被外部所访问。但是可以从类的内部进行间接访问,即通过实例方法来访问。

实例方法:在类中定义的函数,第一个参数是self,指向调用该方法的实例本身。

  1. class Person(object):

  2. def __init__(self, name):

  3. self.__name = name

  4.  
  5. def get_name(self):

  6. return self.__name

get_name就是一个实例方法。调用实例方法必须在实例上调用

  1. p1 = Person('xiaoming')

  2. p1.get_name() # xiaoming

在实例方法内部,可以访问所有实例属性,如果外部需要访问私有属性,可以通过方法调用获得。

类方法

在class中定义的全部是实例方法,实例方法第一个参数self是实例本身。

  1. class Person(object):

  2. count = 0

  3. @classmethod

  4. def how_many(cls):

  5. return cls.count

  6. def __init__(self, name):

  7. self.name = name

  8. Person.count = Person.count + 1

  9.  
  10. print Person.how_many()

  11. p1 = Person('Bob')

  12. print Person.how_many()

通过标记一个@classmethod,该方法将绑定到Person类上,而非类的实例。类方法的第一个参数传入的是类本身,上面的cls.count相当于Person.count。因为在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用。

类方法是通过类来直接调用的,或者通过实例直接来调用。

  1. class ClassA(object):

  2.  
  3. @classmethod

  4. def func_a(cls):

  5. print(type(cls), cls)

  6.  
  7.  
  8. if __name__ == '__main__':

  9.  
  10. ClassA.func_a()

  11.  
  12. ca = ClassA()

  13. ca.func_a()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值