1.面向对象技术简介
- 类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 局部变量:定义在方法中的变量,只作用于当前实例的类。
- 实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
- 实例化:创建一个类的实例,类的具体对象。
- 方法:类中定义的函数。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
2.定义类
Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。本章节我们将详细介绍Python的面向对象编程。
如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程。
lass ClassName:
'类的帮助信息' #类文档字符串
class_suite #类体
"""
类的帮助信息可以通过ClassName.__doc__查看。
class_suite 由类成员,方法,数据属性组成。
"""
init方法
在创建类后,类通常会自动创建一个__init__()方法。该方法是一个特殊的方法,类似JAVA 语言中的构造方法。每当创建一个类的新实例时,Python都会自动执行它。init()方法必须包含一个参数,并且必须是第一参数。self参数是一个指向实例本身的引用,用于访问类中的属性和方法。
在方法调用时会自动传递实际参数self。因此,当__init__()方法只有一个参数时,在创建类的实例时,就不需要指定参数了。
接下来给定实例,来解释上面所提到的内容
class Car:
"""汽车类"""
wheel = "德国制造"
def __init__(self):
print(Car.wheel, "的汽车")
car = Car()
print(car)
print(Car.__doc__)
输出结果
--------------------------------------------------------
德国制造 的汽车
<__main__.Car object at 0x0000023084BBD340>
汽车类
Process finished with exit code 0
在__init__()方法中,除了self参数外,还可以自定义一些参数,参数间使用逗号“,”进行分隔。例如,下面的代码将在创建__init__()方法时,再指定3个参数,分别是a,b,c:
class Car:
"""汽车类"""
wheel = "德国制造"
def __init__(self,a,b,c):
print(Car.wheel, "的汽车有以下的属性:",)
print(a)
print(b)
print(c)
在实例化的时候要传入相应的参数
a1 = "qsz"
b1 = "crud"
c1 = "cuad"
car = Car(a1,b1,c1)
输出结果如下
实例方法和数据成员
所谓实例方法是指在类中定义函数。该函数是一种在类的实例上操作的函数。同__init__()方法一样,实例方法的第一参数必须是self,并且必须包含一个self参数。创建实例的方法的语法格式如下:
class Car:
"""汽车类"""
# 数据成员
wheel = "德国制造"
# 实例方法
def functionName(self, parameterlist):
block
def run (self):
print('起步,夸档,给油')
参数说明:
functionName:用于指定方法名,一般使用小写字母开头。
self:必要参数,表示类的实例,其名称可以是self以外的单词,使用self只是一个习惯而已。
parameterlist:用于指定除self参数以外的参数,各参数间使用逗号“,”进行分隔。
block:方法体,实现的具体功能
调用方式
a1 = "qsz"
b1 = "crud"
c1 = "cuad"
car = Car(a1,b1,c1)
car.run()
print(car.wheel)
这里还需要注意一下 实例属性,实例属性是指定义在类的方法中的属性,只作用于当前实例中,代码如下
class Car:
"""汽车类"""
def __init__(self):
self.a = "轮子" # 定义实例属性(喙)
self.b = "方向盘"
self.c = "座椅"
print(self.beak_1)
print(self.wing_1)
print(self.claw_1)
但是这里需要注意一下,实例属性只能通过实例名访问。如果通过类名访问实例属性,将抛出如图所示的异常。
正确的调用方法
car = Car()
print(car.a)
3.Python内置类属性
- dict : 类的属性(包含一个字典,由类的数据属性组成)
- doc :类的文档字符串
- name: 类名
- module: 类定义所在的模块(类的全名是’main.className’,如果类位于一个导入模块mymod中,那么className.module 等于 mymod)
- bases : 类的所有父类构成元素(包含了一个由所有父类组成的元组)
class Employee:
'所有员工的基类'
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print "Total Employee %d" % Employee.empCount
def displayEmployee(self):
print "Name : ", self.name, ", Salary: ", self.salary
print "Employee.__doc__:", Employee.__doc__
print "Employee.__name__:", Employee.__name__
print "Employee.__module__:", Employee.__module__
print "Employee.__bases__:", Employee.__bases__
print "Employee.__dict__:", Employee.__dict__
输出结果如下
4.类的继承
面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。
通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。
继承语法
在python中继承中的一些特点:
-
1.如果在子类中需要父类的构造方法就需要显式的调用父类的构造方法,或者不重写父类的构造方法。
1.1子类不重写 **__init__**,实例化子类时,会自动调用父类定义的 **__init__**。
class Father(object):
def __init__(self, name):
self.name=name
print ( "name: %s" %( self.name) )
def getName(self):
return 'Father ' + self.name
class Son(Father):
def getName(self):
return 'Son '+self.name
if __name__=='__main__':
son=Son('runoob')
print ( son.getName() )
输出结果:
name: runoob
Son runoob
1.2 如果重写了**__init__** 时,实例化子类,就不会调用父类已经定义的 **__init__**,语法格式如下:
class Father(object):
def __init__(self, name):
self.name=name
print ( "name: %s" %( self.name) )
def getName(self):
return 'Father ' + self.name
class Son(Father):
def __init__(self, name):
print ( "hi" )
self.name = name
def getName(self):
return 'Son '+self.name
if __name__=='__main__':
son=Son('runoob')
print ( son.getName() )
输出结果:
hi
Son runoob
- 2、在调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量。区别在于类中调用普通函数时并不需要带上 self 参数
- 3、Python 总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。
实例
class Parent: # 定义父类
parentAttr = 100
def __init__(self):
print "调用父类构造函数"
def parentMethod(self):
print '调用父类方法'
def setAttr(self, attr):
Parent.parentAttr = attr
def getAttr(self):
print "父类属性 :", Parent.parentAttr
class Child(Parent): # 定义子类
def __init__(self):
print "调用子类构造方法"
def childMethod(self):
print '调用子类方法'
c = Child() # 实例化子类
c.childMethod() # 调用子类的方法
c.parentMethod() # 调用父类方法
c.setAttr(200) # 再次调用父类的方法 - 设置属性值
c.getAttr() # 再次调用父类的方法 - 获取属性值
输出结果如下:
调用子类构造方法
调用子类方法
调用父类方法
父类属性 : 200
5.类属性与方法
类的私有属性
__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。
如果真的必须要访问到这个私有属性的话,可以使用 object._className__attrName( 对象名._类名__私有属性名 )访问属性
类的方法
在类的内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数
类的私有方法
__private_method:两个下划线开头,声明该方法为私有方法,不能在类的外部调用。在类的内部调用 self.__private_methods
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print self.__secretCount
counter = JustCounter()
counter.count()
counter.count()
print(counter.publicCount)
print(counter.__secretCount) # 如果真的报错,实例不能访问私有变量
# object._(1个下划线)className+私有变量名**
print(counter._JustCounter__secretCount)