对象可以使用普通的属于对象的变量存储数据。属于一个对象或类的变量被称为域。对象也可以使用属于类的函数来具有功能。这样的函数被称为类的方法。这些术语帮助我们把它们与孤立的函数和变量区分开来。域和方法可以合称为类的属性。

域有两种类型—— 属于每个实例/类的对象或属于类本身。它们分别被称为实例变量和类变量。类使用class 关键字创建。类的域和方法被列在一个缩进块中。

self

类的方法与普通的函数只有一个特别的区别—— 它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候你不为这个参数赋值,Python 会提供这个值。这个特别的变量指对象本身,按照惯例它的名称是self。

虽然你可以给这个参数任何名称,但是强烈建议你使用self 这个名称—— 其他名称都是不赞成你使用的。使用一个标准的名称有很多优点—— 你的程序读者可以迅速识别它,如果使用self 的话,还有些IDE(集成开发环境)也可以帮助你。

假如你有一个类称为MyClass 和这个类的一个实例MyObject。当你调用这个对象的方法MyObject.method(arg1, arg2) 的时候,这会由Python 自动转为MyClass.method(MyObject, arg1, arg2)—— 这就是self 的原理了。

一个尽可能简单的类如下面这个例子所示。

class Person:
    pass # An empty block

p = Person()
print(p)

对象的方法

我们已经讨论了类/对象可以拥有像函数一样的方法,这些方法与函数的区别只是一个额外的self 变量。

class Person:
    def sayHi(self):
        print('Hello, how are you?')

p = Person()
p.sayHi()
# This short example can also be written as Person().sayHi()

__init__ 方法

这个方法可以用来对你的对象做一些你希望的初始化。注意,这个名称的开始和结尾都是双下划线。

class Person:
    def __init__(self, name):
        self.name = name
    def sayHi(self):
        print('Hello, my name is', self.name)

p = Person('Swaroop')
p.sayHi()

类和对象变量

有两种类型的域—— 类的变量和对象的变量,它们根据是类还是对象拥有这个变量而区分。

类的变量由一个类的所有对象(实例)共享使用。只有一个类变量的拷贝,所以当某个对象对类的变量做了改动的时候,这个改动会反映到所有其他的实例上。对象的变量由类的每个对象/实例拥有。因此每个对象有自己对这个域的一份拷贝,即它们不是共享的,在同一个类的不同实例中,虽然对象的变量有相同的名称,但是是互不相关的。

class Robot:
    '''Represents a robot, with a name.'''

    #A class variable, counting the number of robots
    population = 0

    def __init__(self,name):
        '''Initializes the data.'''
        self.name = name
        print('(Initialize {0})'.format(self.name))

        #When this person is created, the robot
        # adds to the population
        Robot.population += 1

    def __del__(self):
        '''I am dying.'''
        print('{0} is being destroyed!'.format(self.name))

        Robot.population -= 1

    if Robot.population == 0:
        print('{0} was the last one.'.format(self.name))
    else:
        print('There are still {0:d} robots working.'.format(
Robot.population))

    def sayHi(self):
        '''Greeting by the robot.

    Yeah, they can do that.'''
        print('Greetings, my master call me {0}.'.format(self.name)
)

    def howMany():
        '''Prints the current population.'''
        print('We have {0:d} robots.'.format(Robot.population))
    howMany = staticmethod(howMany)

droid1 = Robot('R2-D2')
droid1.sayHi()
Robot.howMany()

droid2 = Robot('C-3P0')
droid2.sayHi()
Robot.howMany()

print("\nRobots can do some work here.\n")

print("Robots have finished their work. So let's destroy them.")

del droid1
del droid2

Robot.howMany()

一个与类变量有相同名字的对象变量会隐藏类变量!

我们也能用如下的方式来定义静态方法

@staticmethod
def howMany():
    '''Prints the current population.'''
    print('We have {0:d} robots.'.format(Robot.population))

Python 中所有的类成员(包括数据成员)都是公共的,所有的方法都是有效的。

只有一个例外:如果你使用的数据成员名称以双下划线前缀比如_privatevar,Python 的名称管理体系会有效地把它作为私有变量。

这样就有一个惯例,如果某个变量只想在类或对象中使用,就应该以单下划线前缀。而其他的名称都将作为公共的,可以被其他类/对象使用。记住这只是一个惯例,并不是Python 所要求的(与双下划线前缀不同)。

继承

class SchoolMember:
    '''Represent any school member.'''
    def __init__(self,name,age):
        self.name = name
        self.age = age
        print('(Initialize SchoolMember:{0})'.format(self.name))

    def tell(self):
        '''Tell my details.'''
        print('Name:"{0}" Age:"{1}"'.format(self.name,self.age),end='')

class Teacher(SchoolMember):
    '''Repressent a teacher.'''
    def __init__(self,name,age,salary):
        SchoolMember.__init__(self,name,age)
        self.salary = salary
        print('(Initialized Teacher:{0})'.format(self.name))

    def tell(self):
        SchoolMember.tell(self)
        print('Salary:"{0:d}"'.format(self.salary))

class Student(SchoolMember):
    '''Represents a student'''
    def __init__(self,name,age,marks):
        SchoolMember.__init__(self,name,age)
        self.marks = marks
        print('(Initialized Student:{0})'.format(self.name))

    def tell(self):
        SchoolMember.tell(self)
        print('Marks:"{0:d}"'.format(self.marks))

t = Teacher('Mrs.Shrividya',30,30000)
s = Student('Swaroop',25,75)

print() #pirnts a blank line

members = [t,s]
for member in members:
    member.tell() # work for both Teacher and Students