[阶段一] 10. Python面向对象编程

python面向对象编程

  • 什么是面向对象?

类是一类具有同一特征的统称,如人类是一个类,张三、李四就是人类的某个具体对象。

利用(面向)对象(属性和方法)去进行编码的过程,就称为面向对象编程。面向对象编程是把构成事物的整个需求按照特点、功能划分,把这些存在共性的部分封装成对象,创建对象的目的不是为了完成某一个步骤,而是为了描述整个事物在整个解决问题的步骤中的行为。

python 中一切皆对象,比如变量也是对象,包括整型(int)、浮点型(float)、字符串(str)、列表(list)、元组(set)、字典和集合(set)。

面向过程:主要分析出解决问题所需要的步骤,用函数把这些步骤一步一步实现,使用的时候一个一个依次调用即可。

面向对象:主要找出问题中的共性问题,作为对象进行操作。

面向过程是一种以过程为中心的编程思想,面向对象是一类以对象为核心的编程思想。

  • 类的定义与调用:

自定义对象数据类型就是面向对象中的类(class)的概念,通过自定义类,可以实例化出具体的对象,类有自己的属性和方法,实例化出来的对象也具备类的属性和方法。

可以把类理解为一个模板,通过这个模板可以创建出无数个具体的实例。类是抽象的模板,而实例是根据类创建出来的一个个具体的对象,每个对象都拥有相同的方法。

类并不能直接使用,通过类创建出来的实例才能使用。类的所有变量称为属性,类的所有函数称为方法。方法和函数不同的是,方法至少要包含一个 self 参数,且方法无法单独使用,只能和类实例出来的对象一起使用。

python 中,使用关键字 class 来声明类,类的名称首字母大写,多单词情况下每个单词首字母大写,这就是“驼峰命名法”。

用法:

扫描二维码关注公众号,回复: 13385812 查看本文章
class ClassName(object):
    attr = something
    
    def 函数名(self):
        函数具体实现代码块
        return 返回值

示例:

# coding:utf-8

class Person(object):
    name = 'xiaobai'

    def sing(self):
        print(f'{
      
      self.name} can sing')

xxx = Person()              #类的实例化
print(xxx.name)             #通过实例化进行属性调用
xxx.sing()                  #通过实例化进行函数调用

结果:

xiaobai
xiaobai can sing
  • self

self 是一个对象,它代表实例化的变量自身。self 是类方法中的必传参数,且必须放在第一个参数位置。

定义类属性的变量可以不用加上 self,但在定义类方法中的变量是必须要加上 self 的。self 中的变量与含有 self 参数的函数可以在类中的任何一个函数内随意调用。

如果在类中定义函数时加了 self 参数,那这个函数是类实例的方法,而不是类的方法。反之,如果在类中定义函数时没有加 self 参数,那这个函数就只是类的方法,而不是类实例的方法。

  • 类的构造函数:

构造函数,是类中的一种默认函数,用来将类实例化的同时,将参数传入类中。构造函数应该定义在类中所有函数的最上面,作为类的第一个函数。

用法:

class ClassName(object):
    def __init__(self, a, b):               #构造函数
        self.a = a
        self.b = b

示例:

# coding:utf-8

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def sing(self):
        print(f'{
      
      self.name} can sing')

    def study(self):
        print(f'{
      
      self.name}\'s age is {
      
      self.age}, so he is an elementary school student')

xiaobai = Person('xiaobai', 10)
print(xiaobai.name)
xiaobai.sing()
xiaobai.study()

结果:

xiaobai
xiaobai can sing
xiaobai's age is 10, so he is an elementary school student

对于一个对象,构造函数 __init__ 标志着对象生命的开始,系统会从内存中内配一个内存块给这个对象。析构函数 __del__ 标志着对象生命的结束,它会删除对象,系统会从内存中释放这个内存块。

  • 私有函数和私有变量:

私有函数与私有变量,就是无法被实例化后的对象调用的类中的函数与变量。

私有函数与私有变量,只希望类内部业务调用使用,不希望被使用者调用。因此,类内部可以调用私有函数与私有变量。

私有函数与私有变量,只需要在变量或函数前添加双下划线 __ 来定义。尽量不要在实例化对象中直接调用私有函数和私有变量。

用法:

class ClassName(object):
    def __init__(self, a):
        self.a = a
        self.__b = b                #私有变量
    
    def __函数名(self):             #私有函数
        函数具体实现代码块
        return 返回值

示例:

# coding:utf-8

class Person(object):
    def __init__(self, name):
        self.name = name
        self.__age = 10

    def __sing(self):
        return f'{
      
      self.name} can sing'

    def sing(self):
        result = self.__sing()
        return result

    def __study(self):
        return f'{
      
      self.name}\'s age is {
      
      self.__age}, so he is an elementary school student'

    def study(self):
        result = self.__study()
        return result

xiaobai = Person('xiaobai')
print(xiaobai.name)
print(xiaobai.sing())
print(xiaobai.study())

结果:

xiaobai
xiaobai can sing
xiaobai's age is 10, so he is an elementary school student
  • python 中的封装:

使用类中的非私有函数,来调用类中不对外的私有属性和方法,就称为 python 中的封装。这样做的目的是保护隐私,明确区分内外。

示例:

# coding:utf-8

class Hello(object):
    def __init__(self, data):
        self.data = data
    def __hello(self):
        print('hello %s' % self.data)

    def hello(self):
        self.__hello()


if __name__ == "__main__":
    say = Hello('world')
    say.hello()

结果:

hello world
  • 装饰器:

装饰器也是一种函数,它可以接受函数作为参数,也可以返回一个新的函数。因此,接收一个函数作为参数,在内部对其进行处理,然后返回一个新的函数,动态的增强函数功能,这就是装饰器。

装饰器本质上是一个高阶函数,它接收一个函数作为参数,然后返回一个新的函数,可以让该函数在不改动源代码的情况下增加其他新功能。

当装饰器和被装饰函数在同一个 py 文件时,装饰器需要定义在被装饰函数的前面,python 代码是自上而下依次执行的(从而使得程序在自上而下执行时可以调用上面定义的装饰器)。

用法:

def out(func_args):             #外围函数
    def inter(*args, **kwargs):             #内嵌函数
        return func_args(*args, **kwargs)
    return inter                #外围函数返回内嵌函数

python 通过一个语法糖@符号来使用装饰器,这样可以避免编写 f = decorate(f) 这样形式的代码。所谓的语法糖便是不使用也可以完成任务,但是使用它可以让代码更简洁。

对于装饰器,需要记住的就是

@decorate
def f():
    pass

其中,

@decorate   等价于  f = decorate(f)

示例:

# coding:utf-8

import time
from functools import reduce

def performance(f):
    def fn(*args, **kw):
        t1 = time.time()                #unix时间戳
        r = f(*args, **kw)
        t2 = time.time()
        print('call %s() in %f s' % (f.__name__, t2 - t1))
        return r
    return fn

@performance
def factorial(n):
    return reduce(lambda x, y: x * y, range(1, n+1))

print(factorial(10))

执行结果:

call factorial() in 0.002750 s
3628800
  • classmethod 装饰器:

classmethod 装饰器的功能是将类函数可以不经过实例化而被直接调用。

用法:

@classmethod
def func(cls,...):
    函数具体实现代码块
    return 返回值

参数 cls 替代普通类函数中的 self,代表当前操作的是类。

示例:

# coding:utf-8

class Test(object):
    def __init__(self, a):
        self.a = a

    def run(self):
        print('run')
        self.dump()

    @classmethod
    def dump(cls):
        print('dump')

t = Test('a')
t.run()
print('-----')
Test.dump()

结果:

run
dump
-----
dump
  • staticmethod 装饰器:

staticmethod 装饰器的功能是将类函数可以不经过实例化而被直接调用。被该装饰器调用的函数不允许传递 selfcls 参数,且无法在该函数内调用其它类函数或类变量。

用法:

@classmethod
def func(...):
    函数具体实现代码块
    return 返回值

函数体内无 selfcls 参数。

示例:

# coding:utf-8

class Test(object):
    def __init__(self, a):
        self.a = a

    def run(self):
        print('run')
        self.dump()

    @staticmethod
    def dump():
        print('dump')

t = Test('a')
t.dump()
print('-----')
Test.dump()

结果:

dump
-----
dump
  • property 装饰器:

property 装饰器的功能是将类函数的执行去掉括号,类似于调用属性(类变量)。

用法:

@property
def func(self):
    函数具体实现代码块
    return 返回值

函数体内只能有 self 参数。

示例:

# coding:utf-8

class Test(object):
    def __init__(self, name):
        self.__name = name

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, value):
        self.__name = value


n = Test('xiaobai')
print(n.name)
n.name = 'xiaohei'
print(n.name)

结果:

xiaobai
xiaohei
  • 类的继承:

继承时类与类之间的一种关系,一个类可以通过继承基类来得到基类的功能。所以把被继承的类称为父类或基类,把继承父类的类称为子类。

通过继承,子类可以拥有父类的所有属性和方法,但父类不会拥有子类自有的属性和方法。

用法:

class Parent_ClassName(object):                #父类
    父类代码实现

class Child_ClassName(Parent_ClassName):                #子类
    子类代码实现

定义子类时,将父类类名作为参数传入子类,就完成了继承。子类实例化后,可以调用自己与父类的属性和方法。

  • super 函数:

super 函数的功能是作为 python 子类继承父类的方法而使用的关键字,当子类继承父类后,就可以使用父类的方法。

用法:

class Parent_ClassName(object):                #父类
    def __init__(self):
        ...

class Child_ClassName(Parent_ClassName):                #子类
    def __init__(self):
        super(Child_ClassName, self).__init__()             #初始化父类的构造函数

示例:

# coding:utf-8

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

    def speak(self):
        print(f'hello!我是{
      
      self.name}')


class Student(Person):
    def __init__(self, name, gender, score, major, stu_num='2018014002'):
        super().__init__(name, gender)
        super().speak()
        self.score = score
        self.major = major
        self.__stu_num = stu_num

    def speak(self):
        print(f'我的学号为{
      
      self.__stu_num},很高兴认识大家')

    def identify(self):
        if self.__stu_num == '2018014002':
            print('我的分组已完成')
        else:
            print('请稍后,马上为你自动分组')

    def set_num(self, new_num):
        self.__stu_num = new_num

    def relation(self):
        if issubclass(Student, Person):
            print('我的父类是Person')
        else:
            print('父类正在查询中')


if __name__ == '__main__':
    stu = Student('小明', '男', 90, '数学')
    stu.speak()
    stu.identify()
    stu.relation()
    print('*****************')
    stu_2 = Student('小红', '女', 89, '英语')
    stu_2.set_num('2018040625')
    stu_2.speak()
    stu_2.identify()

结果:

hello!我是小明
我的学号为2018014002,很高兴认识大家
我的分组已完成
我的父类是Person
*****************
hello!我是小红
我的学号为2018040625,很高兴认识大家
请稍后,马上为你自动分组

对于 super 函数,super(Child_ClassName, self).__init__() 表示初始化父类的 __init__ 函数,也可以初始化父类其它的函数。此外,python3 中,super(Child_ClassName, self).__init__() 可以省略为 super().__init__()

  • 类的多态:

多态就是一个类继承了父类并重写父类的方法,即一个类的多种状态就是多态。对于父类中不需要的方法,子类可以选择重构。

多态的目的是为了保留子类中和父类名称相同的方法的功能,这样就可以避免全盘接收父类的方法。

示例:

# coding:utf-8

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

    def speak(self):
        print(f'hello!我是{
      
      self.name}')


class Student(Person):
    def __init__(self, name, gender, stu_num='2018014002'):
        super().__init__(name, gender)
        self.__stu_num = stu_num

    def speak(self):
        print(f'我的学号为{
      
      self.__stu_num},很高兴认识大家')


if __name__ == '__main__':
    per = Person('小白', '男')
    stu = Student('小明', '男')
    per.speak()
    stu.speak()

结果:

hello!我是小白
我的学号为2018014002,很高兴认识大家

上例中,父类中的 speak 函数与子类中的 speak 函数名称相同,但功能不一样,这就是类的多态。

  • 多重继承:

一个子类继承多个父类,这就是多重继承。

将被继承的父类类名作为参数传入子类,从左到右依次继承。如果多个父类中有名称相同的方法,第一个父类中的该方法会起作用。

多重继承中,继承关系可以顺序延续,后续子类可以继承前驱父类。例如,A类继承B类,B类继承C类,因此A类也继承了C类。

用法:

class Parent1_ClassName(object):                #父类1
    父类1代码实现

class Parent2_ClassName(object):                #父类2
    父类2代码实现

class Parent3_ClassName(object):                #父类3
    父类3代码实现

class Child_ClassName(Parent1_ClassName, Parent2_ClassName, Parent3_ClassName):                #子类
    子类代码实现

示例:

# coding:utf-8

class Human(object):
    def speak(self):
        print('human can speak')


class Person(object):
    def speak(self):
        print('hello world')

    def work(self):
        print('person work every week')


class Student(Human, Person):
    def work(self):
        print('student\'s work is study')


if __name__ == '__main__':
    stu = Student()
    stu.speak()
    stu.work()

结果:

human can speak
student's work is study
  • 类的高级函数 __str__

__str__ 函数的功能是,如果定义了 __str__ 函数,当 print 当前实例化对象时,会返回该函数的 return 信息。

用法:

def __str__(self):
  return str_type

__str__ 函数一般返回对于该类的描述信息。

  • 类的高级函数 __getattr__

__getattr__ 函数的功能是,当调用的属性或方法不存在时,会返回该函数定义的信息。

用法:

def __getattr__(self, key):
  print(...)

参数 key 表示调用任意不存在的属性名称,返回值可以是任意类型,也可以不返回。

示例:

# coding:utf-8

class Test(object):
    def __str__(self):
        return 'This is a test class'

    def __getattr__(self, item):
        print(f'This {
      
      item} is not exists')


t = Test()
print(t)
t.abc

结果:

This is a test class
This abc is not exists
  • 类的高级函数 __setattr__

__setattr__ 函数的功能是拦截当前类中不存在的属性与值。

用法:

def __setattr__(self, key, value):
    self.__dict__[key] = value

参数 key 表示当前的属性名,value 表示当前的参数对应的值,无返回值。

  • 类的高级函数 __call__

__call__ 函数的功能是将一个类变成一个函数。

用法:

def __call__(self, *args, **kwargs):
    print(...)

可传任意参数,返回值可以是任意类型,也可以不返回。

示例:

# coding:utf-8

class Test(object):
    def __str__(self):
        return 'This is a test class'

    def __getattr__(self, item):
        print(f'This {
      
      item} is not exists')

    def __setattr__(self, key, value):
        self.__dict__[key] = value
        print(self.__dict__)

    def __call__(self, *args, **kwargs):
        print('args is {}'.format(kwargs))


t = Test()
print(t)
t.abc
t.name = 'xiaobai'
print(t.name)
t(name='xiaobai')

结果:

This is a test class
This abc is not exists
{'name': 'xiaobai'}
xiaobai
args is {'name': 'xiaobai'}

猜你喜欢

转载自blog.csdn.net/miss1181248983/article/details/120088542