Python学习笔记8:面向对象
面向对象技术简介
类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
方法:类中定义的函数。
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
局部变量:定义在方法中的变量,只作用于当前实例的类。
实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟”是一个(is-a)”关系(例图,Dog是一个Animal)。
实例化:创建一个类的实例,类的具体对象。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
类定义
class ClassName:
<statement-1>
.
.
.
<statement-N>
类变量和实例变量
通常来说,实例变量是对于每个实例都独有的数据,而类变量是该类所有实例共享的属性和方法。
class Dog:
kind = "canine" # class variable
walk_place = []
def __init__(self, name):
self.name = name # instance variable
上面类Dog中,类属性kind为所有实例所共享;实例属性name为每个Dog的实例独有。
类对象和实例对象
Python中一切皆对象;类定义完成后,会在当前作用域中定义一个以类名为名字,指向类对象的名字。实例对象是类对象实例化的产物。
class Dog:
kind = "canine" # class variable
walk_place = []
def __init__(self, name):
self.name = name # instance variable
def walk(self, place):
self.walk_place.append(place)
dog = Dog("James")
dog.walk("shenzhen")
print(Dog.walk_place)
上面类Dog中,Dog属于类对象,而实例化后的dog则是实例对象。
属性绑定
在定义类时,通常我们说的定义属性,其实是分为两个方面的:
a.类属性绑定
b.实例属性绑定
用绑定这个词更加确切;不管是类对象还是实例对象,属性都是依托对象而存在的。
Python作为动态语言,类对象和实例对象都可以在运行时绑定任意属性。因此,类属性的绑定发生在两个地方:
a.类定义时;
b.运行时任意阶段。
类属性绑定,因为是动态语言,所以可以在运行时增加属性,删除属性。如下代码:
class Dog:
kind = "canine" # class variable
def __init__(self, name):
self.name = name # instance variable
Dog.color = "yellow"
print(Dog.kind)
print(Dog.color)
del Dog.color
print(Dog.color) #error
Exception has occurred: AttributeError
type object "Dog" has no attribute "color"
File "D:zPY est est_class.py", line 21, in <module>
print(Dog.color)
实例属性绑定,就是类实例化后再绑定属性。
因为__init__(构造方法)在实例化时执行,所以self.name = name也是属于实例属性绑定。
如下代码:
class Dog:
kind = "canine" # class variable
def __init__(self, name):
self.name = name # instance variable
dog = Dog("James")
dog.color = "yellow"
print(dog.name)
print(dog.color)
self
self代表类的实例,而非类,是当前对象的地址。
self 不是 python 关键字,我们把他换成其他字符也是可以正常执行的。
还有另外一个问题,定义属性或者方法时,哪些需要加self哪些不需要呢?
私有方法,类方法,静态方法
私有方法:以 __两个下划线开头,声明该方法为私有方法,只能在类的内部调用 (类内部别的方法可以调用他),不能在类地外部调用。
类方法:在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例。
静态方法:需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数
class People(object):
country = "china"
#私有方法
def __private_meth(self):
print("this is a private method")
#类方法
def class_meth(self):
print("this is a class method")
#静态方法,不用定义参数
@staticmethod
def getCountry():
return People.country
私有属性与私有方法
# 私有属性
__private_attrs # 不能在类的外部被使用,在内部可以正常调用self.__private_attrs
# 私有方法
__private_methods # 与私有属性类似,不能在类的外部调用,但是内部正常使用self.__private_methods
双下划线、单下划线、头尾双下划线
__name__ # 特殊方法,一般是系统定义名字
__private # 私有类型,只有类对象可以访问,不建议用此方法,__对Python有特殊意义
_protected # 保护类型,类对象和子类对象可以调用,建议用这种方式定义特别的属性方法
lass Person5:
def __p(self):
print("这是私有属性") #内部函数也同样可以任意之间互相调用
def p1(self):
print("这是p1不是私有方法")
def p2(self):
print("这是p2,可以调用p1,也可以调用私有方法__p")
self.p1()
self.__p()
#创建对象
c1 = Person5()
c1.p1()
c1.p2()
#c1.__p() #不能直接私有函数。报错。注意区分系统自带的函数如__str__,外部可以直接调用的。
"""结果如下:
这是p1不是私有方法
这是p2,可以调用p1,也可以调用私有方法__p
这是p1不是私有方法
这是私有属性
"""
继承,多继承
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
class ParentClass1: #定义父类
pass
class ParentClass2: #定义父类
pass
class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
pass
class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
pass
class Animal:
"""
人和狗都是动物,所以创造一个Animal基类
"""
def __init__(self, name, aggressivity, life_value):
self.name = name # 人和狗都有自己的昵称;
self.aggressivity = aggressivity # 人和狗都有自己的攻击力;
self.life_value = life_value # 人和狗都有自己的生命值;
def eat(self):
print("%s is eating"%self.name)
class Dog(Animal):
pass
class Person(Animal):
pass
egg = Person("egon",10,1000)
ha2 = Dog("二愣子",50,1000)
egg.eat()
ha2.eat()
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法。
方法重写
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法,实例如下:
#此示例示意覆盖的含义及方法
class A:
def work(self):
print("A.work被调用")
class B(A):
"""B类继承子A类"""
def work(self):
print("B.work被调用")
b = B()
b.work() #B.work被调用