面向对象过程

- 面向对象(属性与方法)去进行编码的过程

### 面向过程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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值