- 面向对象(属性与方法)去进行编码的过程
### 面向过程VS面向对象
- 编程思想不同:
- 面向过程:是一种以过程为中心的编程思想
- 面向对象:是一类以对象为核心的编程思想
- 特点不同:
- 面向过程:主要分析出解决问题所需要的步骤,用函数把这些步骤一步步实现,使用的十九一个个依次调用即可
- 面向对象:主要找出问题中的共性问题,作为对象进行操作
### 面向对象中常用的术语:
- 类:可以理解为一个模板,通过它可以创建出无数个具体实例
- 对象:类不能直接使用,需要通过类实例化(类的实例又称对象)之后才能使用
- 属性:类中所有的变量称为属性
- 方法:类所拥有的函数通常称为方法:方法可以分为类方法(@classmethod 修饰的方法)
- 静态方法(@staticmethod修饰的方法)和实例方法。类中定义的方法默认是实例方法,实例方法至少要包含一个self参数,只能和类的对象一起使用
- 面向对象最重要的概念就是类和实例,牢记类是抽象的模板,而实例是根据类创建出来的一个个具体的对象,每个对象都拥有相同的方法。
- class首字母大写 class Name(object):
- 类的参数self
- self 是类函数中的必传参数,且必须放在第一个参数位置
- self 是一个对象,他代表实例化的变量自身
- self 可以直接通过点来定义一个类变量 self.name = 'mark'
- self中的变量与含有self参数的函数可以在类中的任何一个函数内随意调用
- 非函数中定义的变量在定义的时候不用self
def sleep3(name):
return name+'3'
class Person(object):
name = None
age = None
def run(self):
print(f'{self.name} 在奔跑')
def jump(self):
print(f'{self.name} 在跳跃')
def work(self):
self.run()
self.jump()
def sleep2(name): # 函数中定义新的函数
return name
result = sleep2(self.name)
print('sleep2 result is ',result)
r3 = sleep3(self.name) # 调用全局函数sleep3
print(r3)
def sleep(): # 类中self是必传参数,否则无法调用
print('sleep')
mark = Person()
mark.run()
mark.name = 'mark'
mark.run()
lily = Person()
lily.run()
lily.name = 'lily'
lily.run()
lily.top = 163
print(lily.top)
# print(mark.top)#报错 top是属于lily这个对象新加的属性
print('========')
lily.work()
# lily.sleep() # 报错,无法调用
print('-------')
print(sleep3('lily'))
- python中self代表类的实例:self在定义类的方法时是必须有的,虽然在调用的时候不必传入对应的参数
- python中只有针对类来说self才有意义,python中所说的self,就是指类中的self
- self只能再python类的方法中使用
- 属性:
- (1)如果变量定义在类下面而不是类的方法下面,那这个变量即是类的属性也是类实例的属性。
- (2)如果变量定义在类的方法下面,如果加了self,那这个变量就是类实例的属性,不是类的属性;如果没加self,这个变量只是这个方法的局部变量,既不是类的属性也不是类实例的属性。
- 方法:
- (1)如果在类中定义函数时加了self,那这个函数就是类实例的方法,而不是类的方法。
- (2)如果在类中定义函数时没有加self,那这个函数就只是类的方法,而不是类实例的方法。
class Dog:
# 定义在类的下面,而不是类的方法下面,那这个变量即是类的属性也是类实例的属性。
color = 'yellow'
name = 'lucy'
# 如果变量定义在类的方法下面,如果加了self,那这个变量就是类实例的属性,不是类的属性;
# 如果没加self,这个变量只是这个方法的局部变量,既不是类的属性也不是类实例的属性。
def __init__(self):
self.a = 13
b = 6
print(b)
# (1)如果在类中定义函数时加了self,那这个函数就是类实例的方法,而不是类的方法。
# (2)如果在类中定义函数时没有加self,那这个函数就只是类的方法,而不是类实例的方法。
def eat1():
print('类的方法')
def eat2(self):
print('类实例的方法')
print(Dog.color)
duoduo = Dog()
print(duoduo.color)
# print(Dog.a) # 报错,找不到类属性a
print(duoduo.a) # 输出13
# print(duoduo.b) # 报错,找不到类实例属性b
Dog.eat1()
# Dog.eat2() # 报错,不能调用,需要传参
# duoduo.eat1() # 报错,不能调用
duoduo.eat2()
构造函数:
class Person(object):
def __init__(self,name,age=None):
self.name = name
self.age = age
def run(self):
print(f'{self.name} 在奔跑')
def jump(self):
print(f'{self.name} 在跳跃')
def work(self):
self.run()
self.jump()
print(f'{self.name} 的年龄是 {self.age}')
mark = Person(name='mark')
mark.work()
print('========')
mark.name = 'mark.li' # 能正常修改
mark.work()
print('-------')
luck = Person(name='luck',age=16)
luck.work()
- 对象的生命周期,python中会自动管理内存周期
- 实例化__init__:对象的生命周期开始(内存中分配一个内存块)
- __del__:删除对象(从内存中释放这个内存块)
私有函数和私有变量
- 无法被实例化后的对象调用的类中的函数与变量
- 类内部可以调用私有函数与变量
- 只希望类内部业务调用,不希望被使用者调用
- 私有变量私有函数:变量或者函数前添加__(2个下划线) (补充说明:前后都有的是内置函数)
class Dog(object):
__dog_type = 'dog'
def __init__(self,name,age=None):
self.name = name
self.__age = age
def run(self):
result = self.__run()
print(result)
def __run(self):
return f'{self.__dog_type} {self.name} 在奔跑'
def jump(self):
result = self.__jump()
print(result)
def __jump(self):
return f'{self.__dog_type} {self.name} 在跳跃'
def work(self):
self.run()
self.jump()
print(f'{self.name} 的年龄是 {self.__age}')
mark = Dog(name='mark',age=4)
mark.work()
print(dir(Dog))
re = mark._Dog__jump()
print(re)
# print(mark.__dog_type)# 类外不能调用私有属性
print(mark._Dog__dog_type)
- python中的装饰器
- 是一种函数,可以接受函数作为参数,可以返回函数
- 接收一个函数,内部对其处理,然后返回一个新的函数,动态增强函数功能
- 列子:a函数是装饰器,将c函数作为参数传入给a函数,在a函数中可以选择执行或者不执行c函数,也可以选择对c函数的结果进行二次加工处理
- def out(func_args):外围函数 (传入需要处理的函数)
- def inter(*args,**kwargs): 内嵌函数 (因为不知道传入的func_args传入的是什么参数,所以选择可变参数)
- return func_args(*args,**kwargs) (业务逻辑代码)
- return inter (必须的一步,外围函数返回内嵌函数:所有业务逻辑都在内嵌函数中,不返回内嵌函数,就无法调用)
- 装饰器的用法:方法一:将被调用的函数,直接作为参数传入装饰器的外围函数
- 方法二:使用@符号,将装饰器与被调用函数绑定在一起,@+装饰器函数,放在被调用的函数的上一行,被调用函数正常定义,只需要直接调用被执行函数即可
def check_str(func):
print('func',func)
def inner(*args,**kwargs):
result = func(*args,**kwargs)
print('args',args,kwargs)
if result == True:
return '%s 验证 通过'% result
else:
return '%s 验证 不通过'% result
return inner
@check_str
def test(data):
if len(data) >= 3:
return True
else:
return False
result = test('ok')
print(result)
result = test(data='okk')
print(result)
- 类的常用装饰器:classmethod;staticmethod; property
- classmethod—将类函数,可以不经过实例化而直接被调用
- staticmethod—将类函数可以不经过实例化而直接被调用,被该装饰器调用的函数不许传递self或cls参数,且无法再该函数内调用其他类函数或变量
- property—将类函数的执行免去括弧,类似于调用属性(变量)一样
class Test(object):
def __init__(self,a):
self.a = a
def run(self):
print('run')
self.jump() #正常调用
self.sleep()
@classmethod
def jump(cls):
print('jump')
# cls.run() #不能调用,仍然报错
@staticmethod
def sleep():
print('I want sleep')
t = Test('a')
t.run()
# Test.run() # TypeError: run() missing 1 required positional argument: 'self## '
Test.jump()
print('======')
t.jump()
Test.sleep()
t.sleep()
print('------')
t.run()
class Test1(object):
def __init__(self,name):
self.__name = name
@property
def name(self):
return self.__name
@name.setter
def name(self,value):
self.__name =value
t1 = Test1(name='mark')
print(t1.name)
t1.name = 'mark.li'
print('----',t1.name)
输出:
run
jump
I want sleep
jump
======
jump
I want sleep
I want sleep
------
run
jump
I want sleep
mark
---- mark.li
- 类的继承:通过继承基类来得到基类的功能,被继承的类称作父类或基类,继承者称为子类
- 代码的复用:子类拥有父类所有的属性和方法,父类不具备子类自有的属性和方法
class Parent(object):
def __init__(self,name,sex):
self.name = name
self.sex = sex
def walk(self):
return f'{self.name} can walk'
def is_sex(self):
if self.sex == 'boy':
return f'{self.name} is a boy'
else:
return f'{self.name} is a girl'
class ChildOne(Parent):
def play_football(self):
return f'{self.name} play football very well'
class ChildTwo(Parent):
def play_piano(self):
return f'{self.name} play piano very well'
c_one = ChildOne(name='mark',sex='boy')
re = c_one.play_football()
print(re)
re = c_one.is_sex()
print(re)
c_two = ChildTwo(name='lucy',sex='girl')
re = c_two.play_piano()
print(re)
re = c_two.walk()
print(re)
print('======')
p = Parent(name='Lcuk',sex='boy')
pre = p.walk()# 只能调用自己的,不能调用子类的
print(pre)
- 类的多态实现:子类中重写父类的方法
class Father(object):
def talk(self):
print('father is talking')
def jump(self):
print('具有jump功能')
class Brothor(Father):
def run(self):
print('brother is running')
def talk(self):
print('brother is talking')
class Mark(Father):
def talk(self):
print('mark is talking')
if __name__=='__main__':
br = Brothor()
br.run()
br.talk()
br.jump()
fa = Father()
fa.talk()
ma = Mark()
ma.talk()
class Parent():
def __init__(self,p):
print('hello I am parent %s'% p)
class Child(Parent):
def __init__(self,c):
# def __init__(self, c,p):
print('hello I am child %s'% c)
# super(当前类,类的实例).父类方法,python3中可以不用传
# super(Child,self).__init__(p)
super().__init__(p='luck')
if __name__ == '__main__':
mark = Child(c='mark')
# mark = Child(c='mark',p='luck')
- 类的多重继承:可以继承多个父类(基类)
- class Child(Parent1,Parent2,Parent3...) 逗号隔开,从左向右一次继承
class Tool(object):
def work(self):
print('tool work')
def knife(self):
print('Use a knife to cut fruit')
class Food(object):
def work(self):
print('Food work')
def fruit(self):
print('I like fruit')
class Person(Food,Tool):
def __init__(self,name):
self.name = name
print(f'hello , I am {self.name}')
if __name__ == '__main__':
mark = Person(name='mark')
mark.fruit()
mark.knife()
mark.work()
print(Person.__mro__)#可以查看继承顺序
- 类的高级函数 __str__ __getattr__ __setattr__ __call__
- __str__ 功能:如果定义了该函数,当print当前实例化对象的时候,会返回该函数的return信息
- __getattr__ 当调用的属性或者方法不存在时,会返回该方法定义的信息
- __setattr__ 拦截当前类中不存在的属性和值,并设置,__setattr__(self, key, value)
- __call__ 本质是将一个实例化的类变成一个函数
class Test(object):
pass
class Test1(object):
def __str__(self):
return 'this is a test class(这是一个描述信息)'
def __getattr__(self, key):# 当调用的属性或者方法不存在时,会返回该方法定义的信息
return f' key:{key} 不存在'
def __setattr__(self,key,value): # 处理当前类中不存在的属性和值
print(key,value)
print(self.__dict__)# 每一个类中都有一个这样的内置字典函数
# if key not in self.__dict__:
self.__dict__[key] = value
print(self.__dict__)
def __call__(self, *args, **kwargs):#将一个实例化的类变成一个函数
print('call func ',args,kwargs)
if __name__ == '__main__':
t = Test()
print(t)
# print(t.a) # 报错'Test' object has no attribute 'a'
t1 = Test1()
print(t1)
print(t1.a)
print(t1.hy)
t1.name = 'LUCK'
print(t1.name)
t1('nancy')
t1(name='xiaoyun')
# t1.a.b.c 链式操作
class Test2(object):
def __init__(self,attr=''):
self.__attr = attr
# def __call__(self, *args, **kwargs):
# print('call-func: key is %s'%self.__attr)
def __call__(self,name):
print('call-func2: key is %s'% name)
# def __call__(self):
# print('call-func-test')
def __getattr__(self, key):
if self.__attr:
key = '{}.{}'.format(self.__attr,key)
else:
key = key
print(key)
return Test2(key) # 通过类函数调用类对象,()再次完成一次实例化,类似于递归
t2 = Test2()
t2.a.b.c.d # 调用的__getattr__函数
# t2.a.b.c() # 调用的__call__函数,并且可以传参
t2.a.b.c('niuniu')
t2.name.sex.age(18)



