Python中的对象

作者:操作系统

Python中的对象,方法,类,实例,函数用法解析,python函数

本文实例剖析了Python中的对象,方法,类,实例,函数用法。分享给大家供我们参照他事他说加以考察。具体解析如下:

Python是一个截然面向对象的语言。不止实例是目的,类,函数,方法也都以目的。

复制代码 代码如下:

class Foo(object):
    static_attr = True
    def method(self):
        pass
foo = Foo()

这段代码实际上创设了多少个对象,Foo和foo。而Foo同期又是三个类,foo是这么些类的实例。
在C++里类型定义是在编写翻译时产生的,被储存在静态内部存款和储蓄器里,不能够随便修正。在Python里项目作者是目的,和实例对象同样积攒在堆中,对于解释器来讲类对象和实例对象未有根本上的分别。
在Python中每八个对象皆有友好的命名空间。空间内的变量被存放在指标的__dict__里。那样,Foo类有八个__dict__, foo实例也可以有一个__dict__,但这是七个不等的命名空间。
所谓“定义一个类”,实际上正是雅人成叁个类对象,然后实行生机勃勃段代码,但把实施这段代码时的地点命名空间设置成类的__dict__. 所以您可以写这么的代码:

复制代码 代码如下:

>>> class Foo(object):
...     bar = 1 + 1
...     qux = bar + 1
...     print "bar: ", bar
...     print "qux: ", qux
...     print locals()
...
bar:  2
qux:  3
{'qux': 3, '__module__': '__main__', 'bar': 2}
>>> print Foo.bar, Foo.__dict__['bar']
2 2
>>> print Foo.qux, Foo.__dict__['qux']
3 3

所谓“定义一个函数”,实际上也正是生成三个函数对象。而“定义三个主意”正是生成豆蔻年华
个函数对象,并把那一个指标放在一个类的__dict__中。下边二种定义方法的款式是等价的:

复制代码 代码如下:

>>> class Foo(object):
...     def bar(self):
...         return 2
...
>>> def qux(self):
...     return 3
...
>>> Foo.qux = qux
>>> print Foo.bar, Foo.__dict__['bar']

>>> print Foo.qux, Foo.__dict__['qux']

>>> foo = Foo()
>>> foo.bar()
2
>>> foo.qux()
3

而类世襲正是轻松地定义七个类对象,各自有两样的__dict__:

复制代码 代码如下:

>>> class Cheese(object):
...     smell = 'good'
...     taste = 'good'
...
>>> class Stilton(Cheese):
...     smell = 'bad'
...
>>> print Cheese.smell
good
>>> print Cheese.taste
good
>>> print Stilton.smell
bad
>>> print Stilton.taste
good
>>> print 'taste' in Cheese.__dict__
True
>>> print 'taste' in Stilton.__dict__
False

复杂的地点在`.`其一运算符上。对于类来说,Stilton.taste的意味是“在Stilton.__dict__中找'taste'. 假使没找到,到父类Cheese的__dict__里去找,然后到父类的父类,等等。假使直白到object仍没找到,那么扔二个AttributeError.”
实例同样有谈得来的__dict__:

复制代码 代码如下:

>>> class Cheese(object):
...     smell = 'good'
...     taste = 'good'
...     def __init__(self, weight):
...         self.weight = weight
...     def get_weight(self):
...         return self.weight
...
>>> class Stilton(Cheese):
...     smell = 'bad'
...
>>> stilton = Stilton('100g')
>>> print 'weight' in Cheese.__dict__
False
>>> print 'weight' in Stilton.__dict__
False
>>> print 'weight' in stilton.__dict__
True

不管__init__(卡塔尔(قطر‎是在哪个地方定义的, stilton.__dict__与类的__dict__都无关。
Cheese.weight和Stilton.weight都会出错,因为那八个都碰不到实例的命名空间。而
stilton.weight的索求顺序是stilton.__dict__ => Stilton.__dict__ =>
Cheese.__dict__ => object.__dict__. 那与Stilton.taste的寻觅顺序非常相仿,仅仅是
在最前边多出了一步。

主意有个别复杂些。

复制代码 代码如下:

>>> print Cheese.__dict__['get_weight']

>>> print Cheese.get_weight

>>> print stilton.get_weight
<__main__.Stilton object at 0x7ff820669190>>

咱俩得以看出点运算符把function形成了unbound method. 直接调用类命名空间的函数和点
运算重返的未绑定方法会获得区别的不当:

复制代码 代码如下:

>>> Cheese.__dict__['get_weight']()
Traceback (most recent call last):
  File "", line 1, in
TypeError: get_weight() takes exactly 1 argument (0 given)
>>> Cheese.get_weight()
Traceback (most recent call last):
  File "", line 1, in
TypeError: unbound method get_weight() must be called with Cheese instance as
first argument (got nothing instead)

但那八个谬误说的是一次事,实例方法要求八个实例。所谓“绑定方法”就是轻松地在调用方法时把二个实例对象作为第八个参数。上边那么些调用方法是等价的:

复制代码 代码如下:

>>> Cheese.__dict__['get_weight'](stilton)
'100g'
>>> Cheese.get_weight(stilton)
'100g'
>>> Stilton.get_weight(stilton)
'100g'
>>> stilton.get_weight()
'100g'

聊起底生机勃勃种也等于平时用的调用方式,stilton.get_weight(State of Qatar,是点运算符的另风度翩翩种效应,将stilton.get_weight()翻译成stilton.get_weight(stilton).
与上述同类,方法调用实际上有五个步骤。首先用属性查找的平整找到get_weight, 然后将以此特性作为函数调用,并把实例对象作为第生龙活虎参数。那八个步骤间还未关系。比方说你能够这么试:

复制代码 代码如下:

>>> stilton.weight()
Traceback (most recent call last):
  File "", line 1, in
TypeError: 'str' object is not callable

先找找weight那一个天性,然后将weight做为函数调用。但weight是字符串,所以出错。要注意在这里属性查找是从实例此前的:

复制代码 代码如下:

>>> stilton.get_weight = lambda : '200g'
>>> stilton.get_weight()
'200g'

但是

复制代码 代码如下:

>>> Stilton.get_weight(stilton)
'100g'

Stilton.get_weight的检索跳过了实例对象stilton,所以查找到的是未曾被掩没的,在Cheese中定义的法子。

getattr(stilton, 'weight'State of Qatar和stilton.weight是等价的。类对象和实例对象未有本质区别,getattr(Cheese, 'smell'卡塔尔和Cheese.smell相同是等价的。getattr(卡塔尔(قطر‎与点运算符相比较,好处是属性名用字符串钦命,能够在运转时校勘。

__getattribute__(卡塔尔国是最底部的代码。如若你不重复定义这几个情势,object.__getattribute__()和type.__getattribute__(卡塔尔国就是getattr(卡塔尔的现实贯彻,前面一个用于实例,前者用以类。换句话说,stilton.weight正是object.__getattribute__(stilton, 'weight'卡塔尔国. 覆盖那几个主意是超轻易出错的。比方说点运算符会引致极端递归:

复制代码 代码如下:

def __getattribute__(self, name):
        return self.__dict__[name]

__getattribute__(卡塔尔中还应该有其余的细节,举个例子说descriptor protocol的贯彻,如若重写相当的轻松搞错。

__getattr__()是在__dict__招来没找到的场馆下调用的不二法门。平时的话动态生成属性要用那一个,因为__getattr__(卡塔尔(قطر‎不会干预到其余地方定义的松开__dict__里的属性。

复制代码 代码如下:

>>> class Cheese(object):
...     smell = 'good'
...     taste = 'good'
...
>>> class Stilton(Cheese):
...     smell = 'bad'
...     def __getattr__(self, name):
...         return 'Dynamically created attribute "%s"' % name
...
>>> stilton = Stilton()
>>> print stilton.taste
good
>>> print stilton.weight
Dynamically created attribute "weight"
>>> print 'weight' in stilton.__dict__
False

出于方法只可是是足以视作函数调用的性质,__getattr__(卡塔尔国也得以用来动态变化方法,但近似要介怀Infiniti递归:

复制代码 代码如下:

>>> class Cheese(object):
...     smell = 'good'
...     taste = 'good'
...     def __init__(self, weight):
...         self.weight = weight
...
>>> class Stilton(Cheese):
...     smell = 'bad'
...     def __getattr__(self, name):
...         if name.startswith('get_'):
...             def func():
...                 return getattr(self, name[4:])
...             return func
...         else:
...             if hasattr(self, name):
...                 return getattr(self, name)
...             else:
...                 raise AttributeError(name)
...
>>> stilton = Stilton('100g')
>>> print stilton.weight
100g
>>> print stilton.get_weight

>>> print stilton.get_weight()
100g
>>> print stilton.age
Traceback (most recent call last):
  File "", line 1, in
  File "", line 12, in __getattr__
AttributeError: age

盼望本文所述对我们的Python程序设计具备助于。

本文实例深入分析了Python中的对象,方法,类,实例,函数用法。分享给大家供大家...

本文由金冠53777-金冠娱乐53777-Welcome发布,转载请注明来源

关键词: