1 新式类和经典类
查看父类信息的方法
类名.__bases__
在Python3中默认是新式类, 不管写不写继承
Python2中默认是经典类, 不继承任何, 父类为空
>>> class A:
... pass
...
>>> A.__bases__
()
如果要定义新式类, 需要手动写入继承object
>>> class A:
... pass
...
>>> A.__bases__
()
2 类的定义
定义格式为:
class 类名(父类列表):
类体
其中类名首字母一般大写
父类可以有多个, Python支持多继承
3 类和对象
类体中可以直接写入变量, 这是类的属性, 类和对象都可以调用该属性
类体中可以定义函数, 此函数第一个参数始终是self, 用于给对象绑定方法
其中有个特殊函数是 __init__(self, 参数列表)
该函数在生成对象的时候会调用该方法, 且参数列表需要一一对应
查看类的名称空间
类名.__dict__
基本的定义情况
class Student:
country = 'China'
def __init__(self, ID, NAME, SEX, PROVINCE):
self.id = ID
self.name = NAME
self.sex = SEX
self.province = PROVINCE
def getScore(self):
print(self.score)
def setScore(self, score):
self.score = score
s1 = Student('000', 'weihuchao', 'male', 'chongqing')
print( s1.name )
s1.setScore(100)
s1.getScore()
Student.getScore(s1)
print( id(Student.getScore ) )
print( id(s1.getScore ) )
类的作用
1) 生成对象
对象名 = 类名(参数列表)
2) 属性引用
类名.类属性
#或者
类名.函数(类的对象, 参数列表)
对象的作用
调用属性和绑定方法
其中类的函数和对象的方法是不一样的, 尽管事实上实现的功能一致
对象会先找自己空间是否有属性, 没有就会调用类中的
如果实赋值语句, 则会绑定一个新的属性
解除绑定用del
4 继承
继承会继承父类所有公开的属性和方法
Python支持多继承
Python3的多继承查找是c3算法, 可以使用__mro__查看顺序
类名.__mro__
python2中经典类的多继承查找是 深度优先算法
5 组合和派生
组合是在绑定属性的时候使用别的类的对象
派生就是继承之后绑定新的属性和方法
6 接口和抽象类
接口是光定义函数不实现
但是无法限制子类继承的时候必须实现那些方法
要实现限制子类必须实现那些方法, 可以定义一个抽象类
抽象类是导入abc模块来实现
需要继承内写入 metaclass=abc.ABCMeta
给方法加入装饰器 abc.abstractmethod
具体实现如下
import abc
class Animal(metaclass=abc.ABCMeta):
tag='123123123123123'
@abc.abstractmethod
def run(self):
pass
@abc.abstractmethod
def speak(self):
pass
class People(Animal):
def run(self):
pass
def speak(self):
pass
peo1=People()
print(peo1.tag)
7 super的写法
在继承的时候, 可能会调用父类的方法, 但是由于python可以多继承, 所以直接指定父类来调用函数容易出现多种问题
所以在调用父类方法的时候使用super方法
格式如下
super(当前类名, self).__init__(参数列表)
具体实例为
class People:
def __init__(self,name,sex,age):
self.name=name
self.age=age
self.sex=sex
def walk(self):
print('父类的walk()')
class Chinese(People):
country='China'
def __init__(self,name,sex,age,language='Chinese'):
super(Chinese,self).__init__(name,sex,age)
self.language=language
def walk(self):
super(Chinese, self).walk()
print('子类的walk()')
8 多态
父类引用指向子类对象
具体就是 将子类的对象当做参数传入, 传入给他的父类对象, 用父类对象去调用方法, 实际上是调用的子类的方法而不是父类的方法
具体实例如下
class Animal:
def run(self):
print('动物正在走')
class People(Animal):
def run(self):
print('人正在走')
class Pig(Animal):
def run(self):
print('pig is walking')
class Dog(Animal):
def run(self):
print('dog is running')
def func(obj):
obj.run()
9 封装
在类中, 可以通过将名字在前面加上__(双下划线)来标识这是私有变量
在类中, 可以通过 __属性名 来调用该属性
在类外, 无法通过 __属性名 就找到该属性
事实上, 改变了在定义后该变量名字会变成 _类名__属性名
但是不建议通过这样的方法来调用该参数
因而正常情况下, 会编写一个调用该属性的方法当做对外的接口
具体实例如下
class Student:
def __init__(self, ID, NAME):
self.__id = ID
self.__name = NAME
def getId(self):
print(self.__id)
def setId(self, ID):
self.__id = ID
def getName(self):
print(self.__name)
def setName(self, NAME):
self.__name = NAME
10 使用property
有的类里面可以通过函数来返回相关的属性值, 比如圆类中, 可以计算周长和面积
但是这样的用户体验并不好, 我们希望直接通过 调用属性的形式来访问 这个样的属性值, 此时就可以是用装饰器property
@property装饰器下的函数名, 可以通过 类名.函数名 直接获得该返回值
具体实现代码如下
import math
class Circle:
def __init__(self,radius):
self.radius=radius
@property
def area(self):
return math.pi * self.radius**2
@property
def perimeter(self):
return 2*math.pi*self.radius
c=Circle(7)
print( c.area )
print( c.perimeter )
@property只是获取属性, 还可以通过更多的装饰器来形成类似的 设置属性, 删除属性等
设置属性的装饰器是 @函数名.setter
删除属性的装饰器是 @函数名.deleter
获得属性的装饰器是 @函数名.getter (这个的存在就覆盖了@property)
11 静态方法和类方法
静态方法是使用 装饰器staticmethod来形成的函数
该函数的特点是不需要写入self, 后面的参数列表是正常的参数列表, 而且调用的时候需要一一对应
因而该函数也不会绑定给对象, 而是属于类的属性函数
具体情形如下
class Foo:
@staticmethod
def spam(x,y,z):
print(x,y,z)
print(Foo.spam)
print(Foo().spam)
# <function Foo.spam at 0x0000000000B12620>
# <function Foo.spam at 0x0000000000B12620>
类方法是使用装饰器classmethod
类方法就是将方法绑定给类
类方法第一个参数始终是cls, 代表调用它这个函数的对象的类传入给cls
具体使用如下
class Foo:
@classmethod
def test(cls, x, y):
print(cls, x, y)
Foo.test(1,2)
Foo().test(1,2)
# <class '__main__.Foo'> 1 2
# <class '__main__.Foo'> 1 2
静态方法和类方法可以相互搭配, 形成很好的效果
import time
class Date:
def __init__(self,year,month,day):
self.year=year
self.month=month
self.day=day
@classmethod
def now(cls):
t=time.localtime()
obj=cls(t.tm_year,t.tm_mon,t.tm_mday)
return obj
@classmethod
def tomorrow(cls):
t=time.localtime(time.time()+86400)
return cls(t.tm_year,t.tm_mon,t.tm_mday)
class EuroDate(Date):
def __str__(self):
return '年:%s,月:%s,日:%s' %(self.year,self.month,self.day)
print( EuroDate.now() )
# 年:2017,月:4,日:21