16、面向工具编程(二)

16.1 python中创建类属性

类是模板,而实例则是根据类创建的工具。

绑定在一个实例上的属性不会影响其余实例,然而,类自身也是一个工具,若是在类上绑定一个属性,则一切实例都能够拜候类的属性,并且,一切实例拜候的类属性都是同一个!也就是说,实例属性每个实例各自具有
,相互
自力,而类属性有且惟独一份。

界说类属性能够间接在class 中界说:

class Person(object):

      address = ‘Earth’

       def __init__(self, name):

        self.name = name

因为类属性是间接绑定在类上的,以是,拜候类属性不需求创建实例,就能够间接拜候:

print Person.address

# => Earth

对一个实例挪用类的属性也是能够拜候的,一切实例都能够拜候到它所属的类的属性:

p1 = Person(‘Bob’)

p2 = Person(‘Alice’)

print p1.address

# => Earth

print p2.address

# => Earth

因为Python是静态言语,类属性也是能够静态增加和修正

休学的:

Person.address = ‘China’

print p1.address

# => ‘China’print

p2.address

# => ‘China’

因为类属性惟独一份,以是,当Person类的address改变时,一切实例拜候到的类属性都改变了。

16.2 python中类属性和实例属性名字抵触怎么办

修正

休学类属性会招致一切实例拜候到的类属性局部都受影响,然而,若是在实例变量上修正

休学类属性会发生什么问题呢?

class Person(object):

    address = ‘Earth’

    def __init__(self, name):

        self.name = name

p1 = Person(‘Bob’)

p2 = Person(‘Alice’)

print ‘Person.address = ‘ + Person.address

p1.address = ‘China’

print ‘p1.address = ‘ + p1.address

print ‘Person.address = ‘ + Person.address

print ‘p2.address = ‘ + p2.address

结果如下:

Person.address = Earth

p1.address = China

Person.address = Earth

p2.address = Earth

我们发现,在配置了p1.address = ‘China’ 后,p1拜候 address 确实酿成了 ‘China’,然而,Person.address和p2.address仍然是’Earth’,怎么回事?

缘由是p1.address = ‘China’并没有改变 Person 的 address,而是给p1这个实例绑定了实例属性address ,对p1来讲
,它有一个实例属性address(值是’China’),而它所属的类Person也有一个类属性address,以是:

拜候p1.address ,优先查找实例属性,返回’China’。

拜候p2.address ,p2没有实例属性address,然而有类属性address,因此返回’Earth’。

可见,当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的拜候。

当我们把 p1 的 address 实例属性删除后,拜候 p1.address 就又返回类属性的值 ‘Earth’了:

del p1.address

print p1.address

# => Earth

可见,千万不要在实例上修正

休学类属性,它实际上并没有修正

休学类属性,而是给实例绑定了一个实例属性。

16.3 python中界说实例方式

一个实例的公有属性就是以__扫尾的属性,没法被外部

暮气拜候,那这些属性界说有什么用?

虽然公有属性没法从外部

暮气拜候,然而,从类的外部

暮气是能够拜候的。除能够界说实例的属性外,还能够界说实例的方式。

实例的方式就是在类中界说的函数,它的第一个参数永远是self,指向挪用该方式的实例自身,其余参数和一个普通函数是完全一样的:

class Person(object):

    def __init__(self, name):

        self.__name = name

    def get_name(self):

        return self.__name

get_name(self) 就是一个实例方式,它的第一个参数是self。__init__(self, name)切实也可看作
是一个不凡的实例方式。

挪用实例方式必须在实例上挪用:

p1 = Person(‘Bob’)

print p1.get_name()# self不需求显式传入

# => Bob

在实例方式外部

暮气,能够拜候一切实例属性,如许,若是外部

暮气需求拜候公有属性,能够经由过程方式挪用取得,这种数据封装的方式除能保护外部

暮气数据一致性外,还能够简化外部

暮气挪用的难度。

16.4 python中方式也是属性

我们在class中界说的实例方式切实也是属性,它实际上是一个函数工具:

class Person(object):

    def __init__(self, name, score):

        self.name = name

        self.score = score

    def get_grade(self):

        return ‘A’

p1 = Person(‘Bob’, 90)

print p1.get_grade

# =>bound method Person.get_grade of <__main__.Person object at 0x109e58510

print p1.get_grade()

# => A

也就是说,p1.get_grade 返回的是一个函数工具,但这个函数是一个绑定到实例的函数,p1.get_grade() 才是方式挪用。

因为方式也是一个属性,以是,它也能够静态地增加到实例上,只是需求用types.MethodType() 把一个函数酿成一个方式:

给一个实例静态增加方式并不稀有,间接在class中界说要更直观。

16.5 python中界说类方式

和属性类似,方式也分实例方式和类方式。

class中界说的局部是实例方式,实例方式第一个参数self 是实例自身。

要在class中界说类方式,需求这么写:

经由过程标识表记标帜一个 @classmethod,该方式将绑定到 Person 类上,而非类的实例。类方式的第一个参数将传入类自身,通常将参数名命名为 cls,下面的cls.count 实际上相当于Person.count

因为是在类上挪用,而非实例上挪用,因此类方式没法取得任何实例变量,只能取得类的援用

更多精彩,尽在https://watcherstalk.com