下面是一个学生类定义:
>>> class Student(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
...
>>> stu = Student('张三', 18)
>>> stu.name
'张三'
>>> stu.age
18
class :小写
Student: 类名,首字母大写
object:继承的类,没有的话可以直接写object
init函数:是实例化类的时候调用的函数,前后分别有两个下划线,第一个参数永远是self。
self:实例本身,可以把传入的参数绑定到当前实例。调用时,不用传递该参数。相当于java的this
name,age:实例化传入的参数,也是Student类的属性
另外,类的方法和普通函数没有什么区别,仍然可以用默认参数、可变参数、关键字参数和命名关键字参数。
访问限制
上面的代码,我们可以随便查看、修改其属性的值:
>>> stu.name = '李四'
>>> stu.name
'李四'
>>> stu.age = 11
>>> stu.age
11
如果我们不想被外部修改,可以把name, age私有(private),可以对代码进行保护:
>>> class Student(object):
... def __init__(self, name, age):
... self.__name = name
... self.__age = age
...
>>> s = Student('张三', 18)
>>> s.__name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__name'
如果我们一定要访问、修改,可以在类内部提供get_name ,set_name方法等供外部调用:
>>> class Student(object):
... def __init__(self, name, age):
... self.__name = name
... self.__age = age
... def set_name(self, name):
... self.__name = name
... def get_name(self):
... return self.__name
...
>>> s = Student('张三', 18)
>>> s.get_name()
'张三'
>>> s.set_name('李四')
>>> s.get_name()
'李四'
>>>
面向对象有三大特性:封装、继承、多态
1、封装
在上面的Student类中,每个实例都有name,age属性,我们如果要访问这两个属性,我们可以通过定义一个函数来访问,比如下面的打印一个学生的姓名年龄函数:
>>> class Student(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
...
>>> def print_student(stu):
... print('name:%s, age:%d' %(stu.name, stu.age))
...
>>> print_student(Student('Luffy', 18))
name:Luffy, age:18
>>>
但是,既然name和age属性都在Student类中,为什么我们还要麻烦的在外面定义函数呢?其实我们可以直接在类内部定义一个函数去打印出name和age,这样的函数我们称之为类的方法。把数据和逻辑封装在方法里面,然后通过类对象去调用,调用者不需要知道方法内的实现。
改造上面的代码:
>>> class Student(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def print_student(self):
... print('name:%s, age:%d' %(self.name, self.age))
...
>>> stu = Student('Luffy', 18)
>>> stu.print_student()
name:Luffy, age:18
2、继承
类可以被继承为新的类,被继承的类叫父类、基类、超类, 继承后的类叫子类。子类继承父类之后,就拥有父类的所有方法,类似于子承父业。
>>> class Animal(object):
... def eat(self):
... print('Animal is eating food')
...
>>> class Cat(Animal):
... pass
...
>>> class Dog(Animal):
... pass
...
>>> Cat().eat()
Animal is eating food
>>> Dog().eat()
Animal is eating food
>>>
也可以重写父类的方法, 如:
>>> class Cat(Animal):
... def eat(self):
... print('Cat is eating fish')
...
>>> Cat().eat()
Cat is eating fish
>>> class Dog(Animal):
... def eat(self):
... print('Dog is eating bone')
...
>>> Dog().eat()
Dog is eating bone
>>>
3、多态
多态的意义
对拓展开放:允许增加子类
对修改关闭:不需要改变父类的函数
>>> def print_eat(animal):
... animal.eat()
...
>>> print_eat(Animal())
Animal is eating food
>>> print_eat(Cat())
Cat is eating fish
>>> print_eat(Dog())
Dog is eating bone
>>>
只要print_eat()函数传入的参数是Animal的子类或者本身即可