Python 中的类对象和实例对象

概念

  • 类对象: 就是类本身
  • 实例对象: 由类实例化出来的对象
In [1]: class Person(object):
   ...:     def __init__(self):
   ...:         pass
   ...:

In [2]: print(Person)
<class '__main__.Person'>

In [3]: p1 = Person()

In [4]: print(p1)
<__main__.Person object at 0x0000022E52AB0D30>
  • 上面的 Person 就是类对象,而 p1 则是这个类的实例对象

类对象的使用

  • 类对象支持两种操作:属性引用和实例化。
In [5]: class Person(object):
   ...:     name = "xxx"
   ...:     age = 20
   ...:
   ...:     def __init__(self):
   ...:         pass
   ...:

In [6]: Person.name
Out[6]: 'xxx'

In [7]: Person.age
Out[7]: 20

In [8]: p1 = Person()

In [9]: print(p1.name, p1.age)
xxx 20

In [10]: p1.name = 'yyy'

In [11]: print(Person.name, p1.name)
xxx yyy
  • 上面 In[6]和In[7] 是类对象的属性引用,In[8] 为类对象的实例化

  • 实例对象唯一操作是属性引用,有两种有效的属性名称,数据属性和方法。

类属性、实例属性、类方法、实例方法、静态方法

类属性

  • 类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本;
  • 对于公有的类属性,在类外可以通过类对象和实例对象访问。

实例属性

  • 类的实例化对象的属性,属于实例对象独有。
In [26]: class Person(object):	
    ...:     name = "xxx"	# 类属性
    ...:     age = 20		# 类属性
    ...:
    ...:     def __init__(self):
    ...:        self.addr = "China"		# 实例属性
    ...:
    ...:

In [27]: p1 = Person()

In [28]: Person.name
Out[28]: 'xxx'

In [29]: Person.age
Out[29]: 20

In [30]: p1.name
Out[30]: 'xxx'

In [31]: p1.addr
Out[31]: 'China'

In [32]: Person.addr
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-32-0ed446385bbc> in <module>
----> 1 Person.addr

AttributeError: type object 'Person' has no attribute 'addr'
In [33]: p1.name = "yyy"

In [34]: print(Person.name, p1.name)
Out[34]: 'xxx' 'yyy'
  • 类对象和实例对象都可以访问类属性
  • 类对象无法访问实例属性
  • 类属性只有通过类对象进行修改,实例对象无法修改类属性, 通过实例对象给类属性进行赋值,实际上是给实例对象添加了一条新的属性

类方法

  • 类方法:是类对象所拥有的方法,需要用修饰器"@classmethod"来标识其为类方法,
  • 对于类方法,第一个参数必须是类对象,一般以"cls"作为第一个参数(只是一个参数命名习惯,也可以换成其他的,不过不推荐)
  • 能够通过实例对象和类对象去访问。
In [36]: class Person(object):
    ...:     name = "xxx"
    ...:     age = 20
    ...:
    ...:     def __init__(self):
    ...:         self.addr = "China"
    ...:
    ...:     @classmethod
    ...:     def hello(cls):
    ...:         return "hello world"
    ...:

In [37]: Person.hello()
Out[37]: 'hello world'

In [38]: Person().hello()
Out[38]: 'hello world'
  • 类方法的一个用途就是可以对类属性进行修改, 这样的话,实例对象通过调用类方法也可以对类属性进行修改
In [39]: class Person(object):
    ...:     name = "xxx"
    ...:     age = 20
    ...:
    ...:     def __init__(self):
    ...:         self.addr = "China"
    ...:
    ...:     @classmethod
    ...:     def set_name(cls, value):
    ...:         cls.name = value
    ...:

In [40]: Person().set_name("yyy")

In [41]: Person.name
Out[41]: 'yyy'

实例方法

  • 实例方法:在类中最常定义的成员方法,它至少有一个参数并且必须以实例对象作为其第一个参数,一般以名为"self"的变量作为第一个参数。
  • 在类外实例方法只能通过实例对象去调用,不能通过其他方式去调用(其实类对象可以调用实例方法,只不过需要传一个实例对象作为第一个参数)。
In [42]: class Person(object):
    ...:     name = "xxx"
    ...:     age = 20
    ...:
    ...:     def __init__(self):
    ...:         self.addr = "China"
    ...:
    ...:     def get_addr(self):
    ...:         return self.addr
    ...:

In [43]: p = Person()

In [44]: p.get_addr()
Out[44]: 'China'

In [45]: Person.get_addr()		
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-45-c70e23dcb313> in <module>
----> 1 Person.get_addr()

TypeError: get_addr() missing 1 required positional argument: 'self'

In [46]: Person.get_addr(p)
Out[46]: 'China'
  • 如上所示,类对象直接调用实例方法会报错,但是将一个实例实例对象作为第一个参数传入后,则可以成功调用实例方法

静态方法

  • 需要通过修饰器 @staticmethod 来进⾏修饰,静态⽅法不需要多定义参数

  • 跟普通函数没什么区别,与类和实例都没有所谓的绑定关系,不论是通过类还是实例都可以引用该方法。

  • 静态方法使用场景

    • 如果在方法中不需要访问任何实例方法和属性,纯粹地通过传入参数并返回数据的功能性方法,那么它就适合用静态方法来定义,它节省了实例化对象的开销成本,往往这种方法放在类外面的模块层作为一个函数存在也是没问题的,而放在类中,仅为这个类服务。
In [54]: class Person(object):
    ...:     name = "xxx"
    ...:     age = 20
    ...:
    ...:     def __init__(self):
    ...:         self.addr = "China"
    ...:
    ...:     @staticmethod
    ...:     def sleep(sec):
    ...:         """暂停几秒"""
    ...:         time.sleep(sec)
    ...:     def do_somethings(self):
    ...:         print("do ......")
    ...:         self.sleep(5)
    ...:         print("end ....")
    ...:

In [55]: p = Person()

In [56]: Person.sleep(2)

In [57]: p.sleep(2)

In [58]: p.do_somethings()
do ......
end ....

区别

类对象是否可以调用实例对象是否可以调用
类属性是(可以调用但是无法直接修改)
实例属性
类方法
实例方法否(其实可以调用,但是要传入一个实例对象)
静态方法
  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值