关于类的定义和对象的实例化
作为一门面向对象的语言,类和对象可谓是重中之重,掌握了这一块,才能真正说是学会了python。
先来介绍下关于类和对象的名词吧:
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 实例变量:定义在方法中的变量,只作用于当前实例的类。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟”是一个(is-a)”关系(例图,Dog是一个Animal)。
- 实例化:创建一个类的实例,类的具体对象。
- 方法:类中定义的函数。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法
定义一个简单的类,用于录入员工信息:
class Employee(object):
'所有员工的基类'
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
"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount
先分析上述的代码我们做了什么:
- class Employee:
我们定义了一个类,类名字叫Employee,默认的继承对象是object,object是一切对象的父类也叫基类。 - ‘所有员工的基类’ :
紧跟在类定义后面的这个字符串叫做类的文档字符串,用来写说明文档。 - empCount = 0:
定义类的属性 empCount,用于统计员工编号,可以在外部直接调用。 - def __init__(self, name, salary):
形如def xxx的格式就是在类的内部实现的函数,叫做类的方法,和普通函数不同的是所有类的方法的第一个参数都是self,但在调用的时候不需要传入这个参数,因为参数这个参数表示的是类的实例本身,调用的时候会自动传入。 __init__方法是类的内置方法之一。在实例化的时候执行的第一个方法就是init,它规定了实例化的格式,比如此处我们就要求传入name和salary,2个参数。 - def displayCount(self):
类的普通方法,这里的功能是输出对象的员工号。 - def displayEmployee(self):
类的普通方法,这里的功能是打印对象的员工号和工资。 emp1 = Employee(“Zara”, 2000)
实例化了第一个员工,通过执行Employee.__init__(“Zara”, 2000) 创建了一个对象emp1,但实例化的过程不仅仅做了这些,类的方法会自动绑定到每个对象上,也就是说此时我们可以直接执行emp1.displayCount()和 emp1.displayEmployee()。-emp1.displayEmployee():
调用displayEmployee方法,此时应该会输出
Name : Zara ,Salary: 2000
print “Total Employee %d” % Employee.empCount
打印类的属性.empCount:此时结果为:
Total Employee 2
类的定义完整版
class People(object):
color='yellow' #类的公有属性 可以在外部直接访问
__age=30 #类的私有属性 可以通过方法调用 self.__age 访问
def __init__(self,name): #类的内置方法,初始化的时候需要传入定义的参数
self.Name=name
return self.name
self.sex()
self.__age()
def sex(self,SEX): #类的公有方法,可以在类的外部和对象外部调用
if SEX=='M' || SEX=='W':
self.sex=SEX
self.var1='对象的公有属性'
self.__var2='对象的私有属性'
def __age(self,age_num): #类的私有方法,只能在类的内部调用
self.__age=age_num
@classmethod #类方法修饰器,使得方法可以通过类外部访问
def classaddess(self)
print '类方法'
@staticmethod #静态方法修饰器,使得方法可以通过类外部访问
def staticcard()
print People.color
@property #特性修饰器。将方法变成字段的访问形式
def Bar(self):
print self.Name
修改类的函数
● getattr(obj, name[, default]) : 访问对象的属性。定义当用户访问一个不存在的属性时候的行为。
● getattribute(self,name):定义该类属性被访问时的行为。
● hasattr(obj,name) : 检查是否存在一个属性。返回bool
● setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。定义用户设置一个属性时的行为。
● delattr(obj, name) : 删除属性。定义当用户删除一个属性时候的行为。
hasattr(emp1, ‘age’) # 如果存在 ‘age’ 属性返回 True。
getattr(emp1, ‘age’) # 返回 ‘age’ 属性的值
setattr(emp1, ‘age’, 8) # 添加属性 ‘age’ 值为 8
delattr(empl, ‘age’) # 删除属性 ‘age’
查看类的属性
查看类的属性:
dir(C)
>
[‘class‘, ‘delattr‘, ‘dict‘, ‘doc‘, ‘format‘, ‘getattribute‘, ‘hash‘, ‘init‘, ‘module‘, ‘new‘, ‘reduce‘, ‘reduce_ex‘, ‘repr‘, ‘setattr‘, ‘sizeof‘, ‘str‘, ‘subclasshook‘, ‘weakref‘]
C.class:实例C对应的类(仅新式类)
C.doc:类C对应的文档字符串
C.dict:类C的属性
C.module:类C所在的模块
C.call:将类C变成一个可调用对象。
范例:
class Person:
…: def init(self,name):
…: self.name=name
…: def call(self,friend):
…: print(‘%s 的好基友是%s’ % (self.name,friend))
…:
P=Person(‘小康康’)
P(‘大康康’)
小康康 的好基友是大康康
关于类的继承
继承,顾名思义就知道是它的意思,举个例子说明:你现在有一个现有的A类,现在需要写一个B类,但是B类是A类的特殊版,我们就可以使用继承,B类继承A类时,B类会自动获得A类的所有属性和方法,A类称为父类,B类陈为子类,子类除了继承父类的所有属性和方法,还可以自定义自己的属性和方法,大大增加了代码的复用性。
我们可以继承了object类,object类是所有类的父类,所有的类都默认继承object类,它是一个超级类,如果不写,默认继承object。
继承类的格式:
class A(父类):
…
Python的类支持多继承,下面我们来看一下多继承的格式:
class A: # 定义类 A
…..
class B: # 定义类 B
…..
class C(A, B): # 继承类 A 和 B
…..
多继承其实在需要在父类的位置,直接写多个父类就可以,然后用“,”分开就可以了,C类就同时继承了A类和B类。
Python类的继承注意事项:
1.在继承中类的构造(__init()方法)不会自动调用,它需要在子类的构造中亲自调用。
2. Python总是首先子类中的方法,如果子类没有找到,才回去父类中查找
实例:
import random as r
class Fish():
def __init__(self):
self.x=r.randint(0.10)
self.y=y.randint(0.10)
def move(self):
self.x-=1
print('我的位置是:'self.x,self.y)
class Goldfish(Fish):
pass
class Carp(Fish):
pass
class Salmon(Fish):
pass
class Shark(Fish):
def __init__(self): #此时会自动覆盖父类对象的init方法,因此没有初始坐标。
self.hungry=True
def eat(self):
if self.hungry:
print('我要吃饭')
self.hungry=False
else:
print('我现在不饿')
Shark无法调用move方法,因为init方法被重写了,解决方法:
第一种:调用未绑定的父类方法
def init(self):
Fish.init(self)
self.hungry=True
第二种:使用super方法:自动获取基类方法
def init(self):
super().init()
self.hungry=True
判断对象类型:一个类其实就是一种数据类型
子类方法执行的时候先看子类定义是否重写了该方法,如果没有就去父类找该方法。
super语句:
单继承时super()和init()实现的功能是类似的
class Base(object):
def __init__(self):
print 'Base create'
class childA(Base):
def __init__(self):
print 'creat A ',
Base.__init__(self)
class childB(Base):
def __init__(self):
print 'creat B ',
super(childB, self).__init__()
base = Base()
a = childA()
b = childB()
关于super函数:
代码一:
class A:
def __init__(self):
print("Enter A")
print("Leave A")
class B(A):
def __init__(self):
print("Enter B")
A.__init__(self)
print("Leave B")
class C(A):
def __init__(self):
print("Enter C")
A.__init__(self)
print("Leave C")
class D(A):
def __init__(self):
print("Enter D")
A.__init__(self)
print("Leave D")
class E(B, C, D):
def __init__(self):
print("Enter E")
B.__init__(self)
C.__init__(self)
D.__init__(self)
print("Leave E")
E()
结果:
Enter E
Enter B
Enter A
Leave A
Leave B
Enter C
Enter A
Leave A
Leave C
Enter D
Enter A
Leave A
Leave D
Leave E
执行顺序很好理解,唯一需要注意的是公共父类A被执行了多次。
代码二:
class A:
def __init__(self):
print("Enter A")
print("Leave A")
class B(A):
def __init__(self):
print("Enter B")
super(B, self).__init__()
print("Leave B")
class C(A):
def __init__(self):
print("Enter C")
super(C, self).__init__()
print("Leave C")
class D(A):
def __init__(self):
print("Enter D")
super(D, self).__init__()
print("Leave D")
class E(B, C, D):
def __init__(self):
print("Enter E")
super(E, self).__init__()
print("Leave E")
E()
结果:
Enter E
Enter B
Enter C
Enter D
Enter A
Leave A
Leave D
Leave C
Leave B
Leave E
在super机制里可以保证公共父类仅被执行一次,至于执行的顺序,是按照mro进行的(E.mro)。
:E.mro
(main.E, main.B, main.C, main.D, main.A, object)
关于MRO算法:
http://www.360doc.com/content/16/0719/18/34574201_576833790.shtml