一、“类”有关的知识
1. 面向对象程序设计(OPP,Object-Oriented Programming):是一种计算机编程架构,它认为程序由一系列的对象组成。其中最核心的概念是类和对象,类是对现实世界的抽象,类的实例被称为对象。
1) 中心思想:一切皆对象(Everything is an object.)
2)OPP = 对象+类+继承+多态+消息
3)主要目标:重用性、灵活性、扩展性
2. 类:是一种用户定义的数据类型,就像基本的数据类型byte、int、float等一样,不同的是它是一种复杂的数据类型。类可以用来定义变量,创建对象,还可以派生子类。
3. 每个类都包含了数据说明、一组用于操作数据或传递数据的函数。
4. 因为类的本质是一种数据类型,而不是数据。所以类不存在于内存中,不可以被直接操作,只有被实化为对象时,才会变得可操作。
5. 类的内部封装了属性和方法,即成员数据和成员函数。它描述一个对象能够做什么,以及做的方法。
6. Python支持面向对象的三大特征:封装、继承和多态。子类继承父类,同样可以继承到父类的变量和方法。
二、定义类
1. 定义类的语法如下:
class 类名:
执行语句
零到多个类变量
零到多个类方法
例如:
#定义一个Person类
>>> class Person:
’这是一个学习定义类的案例‘ # 类的说明文档,放在类头和头体之间
#定义一个类变量
hair ='black'
#定义一个构建方法
def __init__(self,name='Jeff',age=8): # 两个变量都有默认值
self.name=name
self.age=age
#定义一个实例方法
def say(self,content):
print(content)
2. 类名:从语法上讲只要是一个合法的标识符即可,但要考虑程序的可读性,类名要求是由一个或多个有意义的单词组成,每个单词的首字母大写,单词和单词之间不用任何人分隔符。
3. 定义类需要注意的几点:
1)定义类和定义函数类似,只是类用class关键字,函数用def关键字。
2)类头包含了class关键字和类名,对冒号(:)作为类的开始,类体包含了类变量和方法,如果不为类定义任意变量和方法,则为一个空类,用pass作为占位符。例如:
>>>class Empty:
pass
3) 类所包含的类变量可以动态的增加或删除。程序也可以为已有的对象增加或删除实例变量。
4)在类中定义的方法默认是实例方法,定义实例方法和定义函数基本想同,实例方法至少应该定义一个参数,该参数通常被命名为self。
三、创建对象
1. 创建对象:调用某个类的方法,即可创建这个类的对象。例如:
#接上面的代码
#将类的Person对象赋值给变量p
>>>p=Person()
2. 创建完对象,就可以使用该对象了。Python的对象有如下作用:
1)操作对象的实例变量:访问实例变量的值,增加、修改、删除实例变量。
#接上面的代码
#直接输出对象p的实例变量name 和 age的值
>>> print(p.name,p.age) #结果:Jeff 8
#访问p的实例变量name ,给它重新赋值
>>>p.name='Mary'
2)操作对象的方法:调用方法,添加或删除方法。
#调用P的say()方法
p.say('welcome to yanghang robot')
#再次输出对象p的实例变量name 和 age的值
>>>print(p.name,p.age) #结果:Mary 8
3. 对象的动态性:
1)动态增加或删除对象的实例变量,例如;
# 直接给对象的变量赋值就可以增加变量
>>> p.skills=['dancing','swimming']
>>> print(p.skills) #结果: ['dancing', 'swimming']
#使用del语句,就可以删除对象的变量
>>> del p.name
>>> print(p.name)
#结果报错:AttributeError: 'Person' object has no attribute 'name'
2)动态的增加和删除方法,例如:
#P对象动态增加的方法不会自行绑定第一个参数self
#先定义一个函数 info()
>>> def info(self): p
print('--info--函数',self)
# 使用info() 函数给 对象p 的方法赋值,就动态增加了方法
>>> p.info=info
>>> p.info(p) #程序必需手动传入参数
# 使用lambda表达式 给 对象p 的方法赋值,就动态增加了方法
>>> p.bar= lambda self: print('---lambda---',self)
>>> p.bar(p) #程序必需手动传入参数
4. 方法之间的依赖:
1) 类体中方法的第一个参数self, 会被自动绑定给对象,所以不需要给第一个参数传值。
2) 方法的第一个参数所代表的对象是不确定的,也就是谁调用该方法,第一个参数就代表谁。例如:
#定义一个dog类
>>> class dog:
#定义一个jump方法
def jump(self):
print('jump......')
#定义一个run方法,run方法调用了jump方法
# run 和 jump 之间就存在依赖
def run (self):
self.jump()
print('run.......')
3)在构造方法中,self参数代表该构建方法正在初始化的对象。
四、类方法和静态方法
1. 方法:是类或对象的行为特征的抽象, Python中方法其实也是函数,所以其定义方法和调用形式都和函数类似。
2. 使用类调用方法:之前的例子都是对象调用方法,如果类直接调用方法,就不会自动绑定self参数,所以要手动传入参数,例如:
#定义一个类user
>>> class user:
#定义一个方法 walk
def walk(self):
print(self,'walking....')
#使用类直接调用方法
>>> user.walk()
#结果报错:TypeError: walk() missing 1 required positional argument: 'self'
#手动传入参数值'abc'
>>> user.walk('abc')
# 结果:abc walking....
3. 类方法和静态方法的区别:
1)类方法的第一个参数会自动绑定到类本身;而静态方法不会绑定到类。
2)使用@classmethod修饰的方法是类方法;使用@staticmethod修饰的方法为静态方法。例如:
#定义一个bird类
>>> class bird:
#用@classmethod修饰类方法fly
@classmethod
def fly(cls):
print('类方法fly',cls)
#用@staticmethod修饰静态方法info
@staticmethod
def info(p):
print('静态方法info',p)
#类直接调用 类方法fly,不需要传入参数
>>> bird.fly() #结果:类方法fly
#类调用info方法,需要手动传入参数
>>> bird.info('abc') #结果: 静态方法info abc
# 构建对象和调用方法
>>> b=bird
>>> b.fly()
>>> b.info('abc')
4. @函数装饰器
1)@classmethod和@staticmethod就是函数装饰器,classmethod和 staticmethod都是Python内置的函数。
2)使用@符号引用已有的函数,可以用来修饰其它函数。我们也可以开发自定义的函数修饰器。
3)当一个函数装饰另一个函数时,实际上是完成了以下两步:
被装饰的函数B, 作为参数被传给了@符号所引用的函数A
将函数B替换成了上一步的返回值,所以函数B已经不是原来的函数。
>>> def funA(fn):
print('A')
return 'Jeff'
>>> @funA #装饰的效果相当于funA(funB),将funB做为了funA的参数,返回了'Jeff'
def funB():
print('B')
>>> print(funB)
# funB已经不再是一个函数,而是一个字符串,运行结果Jeff
六、本节回顾
1) 关于类的知识你知道了哪些?
2)如何定义一个类?
3)如何构建类的对象和使用对象?
4)如何添加、删除、修改方法?
5)类方法和静态方法的区别?
6)@函数装饰器的用法?