python是一门面向对象的语言!!!
1.面向对象
- 类(class):用来描述具有相同的属性和方法的对象的集合,它定义了该集合中每个对象所共有的属性和方法,对象是类的实例
- 方法:类中定义的函数
- 类变量:在整个实例化的对象中是公用的,类变量定义在类中且在函数体之外,通常不作为实例变量使用
- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,也叫做覆盖
- 局部变量:定义在方法中的变量,只作用于当前实例的类
- 实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用self修饰的变量
- 继承:一个子类继承父类的字段和方法
- 实例化:创建一个类的实例,类的具体对象
- 对象:通过类定义的数据结构实例,对象包括两个数据成员(类变量和实例变量)和方法
注意点:
python中的类提供了面向对象编程的所有基本功能,类的继承机制允许多个基类
,派生类可以覆盖基类中的任何方法
,方法中可以调用基类中的同名方法,对象可以包含任意数量和类型的数据
,类实例化后,可以使用其属性,创建一个类之后,可以通过类名访问其属性
1.1.类定义
class ClassName:
<statement -1>
...
< statement - N>
类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性
1.2.类对象
- 类对象支持两种操作:
属性引用和实例化
- 类对象创建后,类命名空间中所有的命名都是有效属性名
- 语法:obj.name
class MyClass:
i = 132
def fun(self):
return 'hello world!'
# 实例化类
x = MyClass()
print(x.i) # 132
print(x.fun()) # hello world!
类有一个名为__init__()
的特殊方法(构造方法),该方法在类实例化时会自动调用
def __init__(self):
self.data = []
类定义了__init__()
方法,类的实例化操作会自动调用__init__()
方法。如下实例化类MyClass,对应的__init__()
方法就会被调用
x = MyClass()
当然,__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
1.3.self
代表类的实例,而非类!!!
类的方法与普通的函数只有一个特别的区别–他们必须有一个额外的第一个参数名称,按照惯例它的名称是self
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt() # <class '__main__.Test'>
从执行结果可以看出,self代表的是类的实例,代表当前对象的地址,而self.class则指向当前类
,self不是python的关键字,我们把它换成Baidu也是可以正常执行的:
class Test:
def prt(Baidu):
print(Baidu)
print(Baidu.__class__)
t = Test()
t.prt() # <class '__main__.Test'>
1.4.类的方法
在类的内部,使用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('darcy', 10, 30)
p.speak() # darcy说:我10岁!self):
1.5.继承
- 子类会继承父类的属性和方法
- 父类名与子类定义在一个作用域内
- 除了类,还可以使用表达式,父类定义在另一个模块中时这一点非常有用
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('darcy', 10, 30)
p.speak() # darcy说:我10岁!self):
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("darcy", 10, 60, 3)
s.speak() # darcy说:我10岁了,我在读3年级!
1.6.多继承
- 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))
# 实例化类
p = People('darcy', 10, 30)
p.speak() # darcy说:我10岁!self):
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("darcy", 25, 80, 4, "python")
# 方法同名,默认调用的是在括号排前的父类的方法
test.speak() # 我叫darcy,我演讲的主题是python
1.7.方法重写
- 如果你的父类的功能不能满足你的需求,你可以在子类中重写你父类的方法
- super()函数是一个调用父类的一个方法
class Parent:
def myMethod(self):
print("调用父类方法")
class Child(Parent):
def myMethod(self):
print("调用子类方法")
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child, c).myMethod() # 用子类对象调用父类已被覆盖的方法
1.8.python子类继承父类构造函数的说明
- 情况1:子类需要自动调用父类的方法:子类不重写
__init__()
,实例化子类时,会自动调用父类定义的__init__()
- 情况2:子类不需要自动调用父类的方法:如果重写了
__init__()
时,实例化子类,就不会调用父类已经定义的__init__()
- 情况3:子类重写__init__()方法又需要调用父类的方法:如果重写了
__init__()
时,要继承父类的构造方法,可以使用super关键字
super(子类名, self).__init__(参数1,参数2.....)
或
父类名.init(self, 参数1,参数2,....)
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):
super(Son, self).__init__(name)
print("hi!")
self.name = name
def getName(self):
return 'Son,'+self.name
if __name__=='__main__':
son = Son("python")
print(son.getName())
1.9.类属性和方法
1.9.1.类的私有属性
__private_attrs
:两个下划线开头,生命该属性为私有,不能在类的外部使用或直接访问,在类内部的方法中使用时self.__private_attrs
1.9.2.类的方法
- 在类的内部,使用
def关键字来定义一个方法,类方法必须包含参数self,而且只能放在第一个参数的位置上
,self代表的是类的实例 - self不是关键字,也可以改为其他的
1.9.3.类的私有方法
__private_method:两个下划线开头,生命该方法为私有方法,只能在类的内部调用,不能在类的外部调用,self.__private_attrs
class Counter:
__privateCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__privateCount += 1
self.publicCount += 1
print(self.__privateCount)
sum = Counter()
sum.count()
sum.count()
# print(sum.__privateCount) # 报错,实例不能访问私有变量
print(sum.publicCount)
class Site:
def __init__(self, name, url):
self.name = name
self.__url = url
def who(self):
print("name:", self.name)
print("url:", self.__url)
def __foo(self):
print("这是私有方法!")
def foo(self):
print("这是公有方法!")
self.__foo()
x = Site("百度", "www.baidu.com")
x.who() # 正常输出
x.foo() # 正常输出
# x.__foo() # 报错
1.9.4.类的专有方法
__init__
:构造函数,在生成对象时调用__del__
:析构函数,释放对象时使用__repr__
:打印,转换__setitem__
:按照索引赋值__getitem__
:按照索引获取值__len__
:获得长度__cmp__
:比较运算__call__
:函数调用__add__
:加运算__truediv__
:除运算__mod__
:求余运算__pow__
:乘方
1.9.4.运算符重载
- 对专有方法进行重载
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector(%d, %d)' % (self.a, self.b)
def __add__(self, other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2, 10)
v2 = Vector(5, -2)
print(v1 + v2) # Vector(7, 8)