定义类

  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

初始化实例属性,当创建实例时,init()方法会被自动调用

  1. class Person(object):
  2. def __init__(self, name, age, sex):
  3. self.age = age
  4. self.name = name
  5. self.sex = sex

属性的访问限制

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

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

  1. class Person(object):
  2. def __init__(self, name):
  3. self.name = name
  4. self._title = 'Mr'
  5. self.__job = 'Student'
  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. print Person.address # => Earth 类属性直接绑定在类上的,可以不实例化直接通过类名调用类属性
  6. p1 = Person('Bob')
  7. p2 = Person('Alice')
  8. print p1.address # => Earth # 通过实例来调用类属性
  9. 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. p1 = Person('Bob')
  7. print Person.count # 1
  8. p2 = Person('Alice')
  9. print Person.count # 1
  10. p3 = Person('Tim')
  11. 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. p1 = Person('Bob')
  7. print Person.count # 1
  8. p2 = Person('Alice')
  9. print Person.count # 2
  10. p3 = Person('Tim')
  11. 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. p1 = Person('Bob')
  6. p2 = Person('Alice')
  7. print 'Person.address = ' + Person.address # zhejiang
  8. p1.address = 'shanxi'
  9. print 'p1.address = ' + p1.address # shanxi
  10. print 'Person.address = ' + Person.address # zhejiang
  11. print 'p2.address = ' + p2.address # zhejiang

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

定义实例方法


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

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

  1. class Person(object):
  2. def __init__(self, name):
  3. self.__name = name
  4. def get_name(self):
  5. return self.__name

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


p1 = Person('xiaoming')
p1.get_name()  # xiaoming

类方法

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

通过标记一个@classmethod,该方法将绑定到Person类上,而非类的实例。

class Person(object):
    count = 0
    @classmethod
    def how_many(cls):
        return cls.count
    def __init__(self, name):
        self.name = name
        Person.count = Person.count + 1

print Person.how_many()
p1 = Person('Bob')
print Person.how_many()

类方法的第一个参数传入的是类本身,上面的cls.count相当于Person.count。类方法是通过类来直接调用的,或者通过实例直接来调用。