Python面向对象

来源于菜鸟教程https://www.runoob.com/python3/python3-class.html)

类定义

语法格式如下:

class ClassName:
<statement-1>
.
.
.
<statement-N>

类对象

知识补充:构造方法

基本概念:构造方法是一种特殊的方法,它是一个与类同名的方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法。构造方法和其他方法一样也可以重载。

备注:

  1. 构造方法作用:(1).构造出来一个类的实例 (2).对构造出来个一个类的实例(对象)初始化。

  2. 构造方法的名字必须与定义他的类名完全相同,没有返回类型,甚至连void也没有。

  3. 主要完成对象的初始化工作,构造方法的调用是在创建一个对象时使用new操作进行的。

  4. 类中必定有构造方法,若不写,系统自动添加无参构造方法。接口不允许被实例化,所以接口中没有构造方法。

  5. 构造方法分为两种:无参构造方法有参构造方法

  6. 构造方法不能被子类继承

  7. 子类创建对象时,会先去创建父类的对象。 默认是去调用父类的无参构造方法。

——百度百科

区分:

Python中的构造方法的形式为 def __init__(self)

  • 类有一个名为 __init__() 的特殊方法(构造方法),该方法在类实例化时会自动调用,如:

def __init__(self):
self.data = []

其中,self代表类的实例,而非类。

  • __init__() 方法可以有参数,参数通过 __init__() 传递到类的实例化操作上。例如:

class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) # 输出结果:3.0 -4.5

此时,使用实例化语句

x = Complex(3.0, -4.5)

填入3.0 -4.5的时候,

提示:

  • 类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是self

  • self代表类的实例。self的名字并不是规定死的,也可以使用this,但是最好还是按照约定是用self

例如:

class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()

执行结果为:

<__main__.Test instance at 0x100771878>
__main__.Test

提示:

  1. self 代表的是类的实例,代表当前对象的地址,而 self.class指向类

  2. self 不是Python关键字,我们把他换成其他变量名也是可以正常执行的。

类的方法

  • 在类的内部,使用def关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数self, 且为第一个参数,self代表的是类的实例。例如:

#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
# 实例化类
p = people('Sublime.',10,30)
p.speak()

输出结果为:Sublime. 说: 我 10 岁。

继承

知识补充:继承

基本概念继承面向对象软件技术当中的一个概念,与多态、封装共为面向对象的三个基本特征。 继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。

继承(英语:inheritance)是面向对象软件技术当中的一个概念。如果一个类别A“继承自”另一个类别B,就把这个A称为“B的子类别”,而把B称为“A的父类别”也可以称“B是A的超类”。继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。另外,为子类别追加新的属性和方法也是常见的做法。 一般静态的面向对象编程语言,继承属于静态的,意即在子类别的行为在编译期就已经决定,无法在执行期扩充。

备注

  1. 子类拥有父类的特征,而父类没有,父类更通用,子类更具体,(特征包括属性和方法,自身的特性,拥有父类没有的)

  2. 在子类中可以继承父类得那些东西,哪些不可以继承 父类中public,protected修饰的属性,方法可以继承,private修饰的属性和方法不能被继承(Python中私有属性为:__变量名__,)。

  3. 规则: 创建子类对象的时候,首先调用的是父类的无参构造方法创建一个父类对象。

  4. 继承并非以继承类别的“行为”为主,而是继承类别的“型态”,使得元件的型态一致。

——百度百科

类的继承:派生类的定义如下:

class DerivedClassName(BaseClassName1):
<statement-1>
.
.
.
<statement-N>

其中,BaseClassName1为被继承的父类(基类),DerivedClassName为继承后的子类(派生类)。

示例如下:

#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
s = student('ken',10,60,3)
s.speak()

输出结果为:ken 说: 我 10 岁了,我在读 3 年级

多继承

class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>

注意:

注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索(即方法在子类中未找到时,从左到右查找父类中是否包含方法。)

#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
#另一个类,多重继承之前的准备
class speaker():
topic = ''
name = ''
def __init__(self,n,t):
self.name = n
self.topic = t
def speak(self):
print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
#多重继承
class sample(speaker,student):
a =''
def __init__(self,n,a,w,g,t):
student.__init__(self,n,a,w,g)
speaker.__init__(self,n,t)
test = sample("Tim",25,80,4,"Python")
test.speak() #方法名同,默认调用的是在括号中排前地父类的方法

超类(调用父类)

子类继承父类构造函数

  • 如果在子类中需要父类的构造方法就需要显式地调用父类的构造方法,或者不重写父类的构造方法。

  • 子类不重写 __init__,实例化子类时,会自动调用父类定义的__init__

  • 如果重写了__init__ 时,实例化子类,就不会调用父类已经定义的 __init__

  • 如果重写了__init__时,要继承父类的构造方法,可以使用 super() 方法。

super()方法

使用super()方法,用于调用父类(超类)。

super(type[, object-or-type])
  • type -- 类。

  • object-or-type -- 类,一般是 self

例如:

class FooParent(object):
def __init__(self):
self.parent = 'I\'m the parent.'
print ('Parent')
def bar(self,message):
print ("%s from Parent" % message)
class FooChild(FooParent):
def __init__(self):
# super(FooChild,self) 首先找到 FooChild 的父类(就是类 FooParent),然后把类 FooChild 的对象转换为类 FooParent 的对象
super(FooChild,self).__init__()
print ('Child')
def bar(self,message):
super(FooChild, self).bar(message)
print ('Child bar fuction')
print (self.parent)
if __name__ == '__main__':
fooChild = FooChild()
fooChild.bar('HelloWorld')

有关__init__()构造函数的超类:

情况一:子类需要自动调用父类的方法:子类不重写__init__()方法,实例化子类后,会自动调用父类的__init__()的方法。

情况二:子类不需要自动调用父类的方法:子类重写__init__()方法,实例化子类后,将不会自动调用父类的__init__()的方法。

情况三:子类重写__init__()方法又需要调用父类的方法:使用super关键词:

super(子类,self).__init__(参数1,参数2....)
class Son(Father):
def __init__(self, name):
super(Son, self).__init__(name)

方法重写与调用父类

class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print ('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法

类属性与方法

私有:以双下划线开头(如__name

私有属性

__private_attrs两个下划线开头,声明该属性为私有不能在类的外部被使用或直接访问。

类的内部使用:self.__private_attrs

私有方法

__private_method: 两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。

类的内部使用:self.__private_methods

类的专有方法

  • __init__: 构造函数,在生成对象时调用

  • __del__ : 析构函数,释放对象时使用

  • __repr__ : 打印,转换

  • __setitem__ : 按照索引赋值

  • __getitem__: 按照索引获取值

  • __len__: 获得长度

  • __cmp__: 比较运算

  • __call__: 函数调用

  • __add__: 加运算

  • __sub__: 减运算

  • __mul__: 乘运算

  • __truediv__: 除运算

  • __mod__: 求余运算

  • __pow__: 乘方