一 什么是面向对象
定义:利用面向对象(属性和方法)的过程去进行编码 自定义面向数据类型就是可面向对象中的类 关键字:class 声明类,名称首字母大写,多单词每个首字母大写
1 类的创建及使用
# 创建
class Person(object): # 通用对像
name = '小熊' # 类属性
def dump(self) # 类方法
print(f'{self.name})
### 缩进应该统一
# 实例化(使用)
xiong = Person() # 实例化
print(xiong.name) # 实例化名字加点调用类属性
xiong.dump() # 实例化名字加点调用类方法
补充
(1)想在类函数中调用属性,需要添加 self.属性名
(2)self 有两种功能 :可以调用类属性;同时也可以将函数定义到类中
2 类的参数self
- 是类函数中的必传函数,且必须放在第一个参数
- self是一个对象,可以实例化类变量自身
- 可以通过点定义一个类变量
“self.name=name
” - self的变量和有self的参数的函数可以在类中任何一个函数随意调用
3 类的构造函数(方法)
- 是类的默认函数,用于实例化的同时,将参数传入类中
- 创建方法
# 创建
class Person(object): # 通用对像
name = '小熊' # 类属性
def dump(self) # 类方法
print(f'{self.name})
### 缩进应该统一
# 实例化(使用)
xiong = Person() # 实例化
print(xiong.name) # 实例化名字加点调用类属性
xiong.dump() # 实例化名字加点调用类方法
对象的生命周期(Python中万物皆对象)
- 1 当被重新赋值员变量就结束使用
- 2 实例化之后是对象的开始,但默认会存在__del__,不用调用
4 私有函数与私有变量(封装)
- 无法被实例化后对象调用类中的函数和变量
- 类内部可以调用私有函数与私有变量
- 目的:只希望类内部逻辑使用,不希望被调用者使用
- 定义方法:在私有变量和私有函数的名字前加“__”两个下划线,后面不需要添加
# 私有变量与私有函数
class person (object):
def __init__(self,a,b):
self.name = name
self.__age = age # 私有变量
def __run (self): # 私有函数
print('我正在跑步')
5 装饰器
- 本质:函数
- 特点:可以接受函数作为参数,同时可以返回一个函数
- 原理:接收一个函数,内部对其调用和处理,然后返回一个新函数,动态增强函数功能
- 流程:将C函数在A函数中执行,在A函数中可以执行或不执行C函数,也可以对C函数的结果进行二次处理
- 使用方法
# 定义
def check_str(func): # 外围函数
print('func:', func)
def inner(*args, **kwargs): # 内嵌函数
print('args:', args, kwargs)
result = func(*args, **kwargs)
if result == 'ok':
return 'result is %s' % result
else:
return 'result is failed:%s' % result
return inner # 返回内嵌函数
# 使用
@check_str
def test(data):
return data
result = test(data='no')
print(result)
result = test(data='ok')
print(result)
常用的装饰器
6 类的继承与多态
- 子类定义时,可将父类传入子类参数中
- 子类实例化可以使用父类的函数与变量
- 继承分单继承和多继承。(多类继承时,若多个父类有相同方法名,子类实例化使用时,在父类寻找时,按继承时的参数顺序从往右)
# 1 2个父类
class Tool(object):
def work(self):
return 'tool work'
def car(self):
return 'car will run'
class Food(object):
def work(self):
return 'food work'
def cake(self):
return 'i like cake'
# 继承父类的子类
class Person(Food, Tool):
pass
if __name__ == '__main__': # 程序入口
p = Person()
p_car = p.car()
p_cake = p.cake()
print(p_car)
print(p_cake)
p_work = p.work()
print(p_work)
print(Person.__mro__)
- 多态: 如果父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法
class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print ('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法
- 类的super函数(可以在继承时,同时调用父类的构造函数)
class Parent(object):
def __init__(self, p):
print('hello i am parent %s ' % p)
class Child(Parent):
def __init__(self, c):
super().__init__('parent')
print('hello i am child %s ' % c)
if __name__ == '__main__':
c = Child(c='Child')
7 类的高级函数
- str 如果定义了该函数,当打印实例化时,会输出该函数的return语句(常用于输出该类的说明信息)返回值必须为string
- getatter 当调用的属性或方法不存在时,,会返回该函数的信息
- setatter 拦截当前类中不存在的属性与值
- call 类通过提供__call__()方法可以模拟函数的行为,如果一个对类提供了该方法,就可以像函数一样使用,实例化之后可以直接使用
class Test(object):
def __str__(self):
return 'this is a test class'
def __getattr__(self, key):
return '这个key:{}并不存在'.format(key)
def __setattr__(self, key, value):
self.__dict__[key] = value
print(self.__dict__)
def __call__(self, a):
print('call func will start')
print(a)
t = Test()
print(t)
print(t.a)
print(t.b)
t.name = '小慕'
print(t.name)
t('dewei')
# t.a.b.c 链式操作
class Test2(object):
def __init__(self, attr=''):
self.__attr = attr
def __call__(self, name):
return name
def __getattr__(self, key):
if self.__attr:
key = '{}.{}'.format(self.__attr, key)
else:
key = key
print(key)
return Test2(key)
t2 = Test2()
name = t2.a.b.c('dewei')
print(name)
result = t2.name.age.sex('ok')
print(result)
### this is a test class
这个key:a并不存在
这个key:b并不存在
{'name': '小慕'}
小慕
call func will start
dewei
a
a.b
a.b.c
dewei
name
name.age
name.age.sex
ok
###