[Python][华为云Python编程创造营][学习笔记][06_类与对象]

举报
John2021 发表于 2021/11/07 15:32:50 2021/11/07
【摘要】 1,面向对象和面向过程    1.1,两种思维方式        面向对象和面向过程是程序中两种常见的思维方式。        1.1.1,面向过程            - 面向过程:把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。            - 优点:将复杂的问题流程化...

1,面向对象和面向过程

    1.1,两种思维方式

        面向对象和面向过程是程序中两种常见的思维方式。

        1.1.1,面向过程

            - 面向过程:把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。
            - 优点:将复杂的问题流程化,进而简单化。
            - 缺点:扩展性差。

        1.1.2,面向对象概述

            - 面向对象编程-Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
            - 面向过程:把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。
            - Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)概念。
            - 面向对象:核心是对象二字,特征和技能的结合体。
            - 优点:可拓展性高。
            - 缺点:编程复杂度高。
            - 应用场景:用户需求经常变化,互联网应用,游戏,企业内应用等。

        1.1.3,把大象装进冰箱

        img1.PNG

2,类和对象

    - 类:类作为设计蓝图来创建对象的代码段,它描述了对象的特征,该对象具有什么样的属性,怎样使用对象完成一些任务,它对事件进行怎样的响应等。
    - 对象:对象是类的一个实例,通常通过调用类的一个构造函数来创建它。

3,面向对象中的术语

    - 封装:封装是一个概念,它的含义是把方法、属性、事件集中到一个统一的类中,并对使用者屏蔽其中的细节。
    - 继承:继承是一种创建类的方法,在现有类(被继承的类)基础上,进行拓展生成新的类,被称为子类。被继承的类成为父类、基类、超类。
    - 多态:一个同样的函数对于不同的对象可以具有不同的实现。

4,Python中的面向对象

    - Python是一门面向对象的编程语言,语言中内建了面向对象的特征。在Python中万物皆对象。
    - Python支持多继承。
    - Python创建类的方式如下:
        class 类名(父类):  # class关键字声明类,父类可以是多个,默认继承object
            '''类说明文档'''
            ...类体...

    4.1,继承(1)

        - 编写了一个名为Animal的class,有一个run()方法可以直接打印:

class Animal(object):
    def run(self):
        print("Animal is running...")

        - 当我们需要编写Dog和Cat类时,就可以直接从Animal类继承:

class Dog(Animal):
    pass
class Cat(Animal):
    pass
dog=Dog()
dog.run()  # Animal is running...
cat=Cat()
cat.run()  # Animal is running...

            对于Dog来说,Animal就是它的父类,对于Animal而言,Dog就是它的子类,Cat和Dog类似。

    4.2,继承(2)

        - 继承还可以一级一级地继承下来

        img2.png

    4.3,多态性:子类中定义新方法

        - 事实上,Python的多态性就体现在通过覆盖父类的方法来实现,在运行时根据传递的对象引用,来调用相应的方法。Python默认是多态的。

class Animal:
    def run():
        raise AttributeError("子类必须实现这个方法")
class People(Animal):
    def run(self):
        print("人正在走")  # 人正在走
class Dog(Animal):
    def run(self):
        print("狗在走")  # 狗在走
class Cat(Animal):
    def run(self):
        print("猫在走")  # 猫在走
p=People()
p.run()
d=Dog()
d.run()
c=Cat()
c.run()

    4.4,私有化

        - 默认情况下,属性在Python中都是"public",类所在模块和导入了类所在模块的其他模块都可以访问到。如果类中的某些属性不想被外界访问或者继承可以对其私有化。
        - 模块级的私有化:在属性或方法前加上一个下划线即可。防止模块的属性用"from mymodule import *"来加载,它只可以在本模块中使用。
        - 完全私有化:只能自己访问。在方法或属性前加双下划线。(Python中的完全私有化是一个假的私有化。它的作用其实是将之前的属性或方法名改为了'_类名._属性/方法')。

    4.5,Python对于封装性的看法

        - 设计封装的逻辑往往要耗费一定的精力,并且会导致代码更加长不易读等等。
        - Python的语言风格没有特别强调封装性。它主张程序员自己通过更加严谨的方式组织程序以避免出错,而不是通过在语言层面实现封装达到这一点。
        - 但是,在Python中仍然可以实现对象的(非严格意义上的)封装。

    4.6,对象的封装性(1)

        - 例如在High_school_student类中,虽然数据已经被封装在类里面,但是我们还是可以通过外部访问其中的变量。我们可以在外部对age进行修改。

class High_school_student():
    def __init__(self):
        self.age=18.0
        self.sex='M'
student_a=High_school_student()
print(student_a.age)  # 18.0
student_a.age=28.0
print(student_a.age)  # 28.0

    4.7,对象的封装性(2)

        - 如果我们希望某些内部属性不被外部访问,我们可以在属性名称前加上两个下划线"__",表示将该属性成员私有化,该成员在内部可以被访问,但是在外部是不能够访问的。

class High_school_student():
    def __init__(self):
        self.__age=18.0
        self.__sex='M'
student_a=High_school_student()
print(student_a.__age)  # AttributeError: 'High_school_student' object has no attribute '__age'

    4.8,对象的封装性(3)

        - 成员私有化并不是代表完全不能够从外部访问成员,而是提高了访问的门槛,防止意外或者随意改变成员,引发错误。我们仍然可以通过_类名+私有变量,对变量进行访问。

class High_school_student():
    def __init__(self):
        self.__age=18.0
        self.__sex='M'
student_a=High_school_student()
student_a.__age=18.8
print(student_a._High_school_student__age)  # 18.0
print(student_a.__age)  # 18.8

    4.9,对象的封装性(4)

        - 成员私有化不仅包括属性的私有化,也包括了方法的私有化,在方法名称前加上__(两下划线)也可以使得函数只能被内部访问,不能够被外部访问:

class High_school_student():
    def __init__(self):
        self.age=18.0
        self.sex='M'
    def __missing_detecting(self):
        if self.age=='':
            print("This is a missing value!")
        else:
            print("This is not a missing value!")
student_a=High_school_student()
student_a.__missing_detecting()

    5.0,给对象添加不存在的属性和方法

        - 在Python中实例化对象以后,动态的添加类的属性和方法同样会影响对象。
        - 动态的属性和方法也可以直接添加在对象上。添加在对象上不会反过来影响类。

class Person(object):
    def __init__(self,age,name):
        self.age=age
        self.name=name
p1=Person(18,'zhangsan')
def eat(self):
    print("%s吃%s"%(self.name,self.food))
Person.food="鸡蛋"
Person.eat=eat
p1.eat()

    5.1,面向对象-函数与方法

        - 函数:函数是封装了一些独立的功能,可以直接调用,能将一些数据(参数)传递进去进行处理,然后返回一些数据(返回值),也可以没有返回值。可以直接在模块中进行定义使用。
        - 方法:方法和函数类似,同样封装了独立的功能,但是方法是只能依靠类或者对象来调用的,表示针对性的操作。
        - 区别:函数在Python中独立存在,可直接使用的,而方法是必须被别人调用才能实现。静态方法除外(与类和对象无关,通过类名和对象名均可被调用,属函数)。

    5.2,实例方法、静态方法与类方法

        - 实例方法,第一个参数为self,调用时需要传递实例给self。
        - 静态方法,和类有关,但是在使用时并不需要类或者实例本身(和函数类似)。
            通过@staticmethod实现

class C():
    @staticmethod
    def f():
        print("HuaweiCloud")
C.f()  # HuaweiCloud,静态方法无需实例化
hw=C()
hw.f()  # HuaweiCloud,实例化后调用也可以

        - 类方法,第一个参数cls,调用时需要传递类型给类方法。对应的函数不需要实例化,不需要self参数,但第一个参数需要是表示自身类的cls参数,可以用来调用类的属性。
            通过@classmethod实现

class A():
    bar = 1
    def func1(self):
        print("huawei")
    @classmethod
    def func2(cls):
        print("huawei-classmethod")
        print(cls.bar)
        cls().func1()
A.func2()
# 输出结果
# huawei-classmethod
# 1
# huawei

5,魔法方法

    魔法方法是指Python内部已经包含的,被双下划线所包围的方法(__init__),在面向对象的Python中,这些方法适用范围广泛,且功能强大。

    5.1,常用魔法方法(1)

        - __new__(cls[,...]):创建实例时首先调用的方法(构造方法)。
        - __init__(self[,...]):对象初始化方法(new方法返回对象后,调用init方法进行属性的初始化)。
            new相较于init使用较少。
            new可用于单例模式。

class Employee:
    def __new__(cls):
        print("__new__ magic method is called")
        inst=object.__new__(cls)
        return inst
    def __init__(self):
        print("__init__ magic method is called")
        self.name="Satya"
emp=Employee()
print(emp)
# 输出结果
# __new__ magic method is called
# __init__ magic method is called

    5.2,常用魔法方法(2)

        - __del__(self):析构方法,当实例化对象被彻底销毁时调用(实例化对象的所有指针都被销毁时被调用)。
        - __len__(self):定义当被len()调用时的操作。
            - len(obj)
        - __bool__(self):定义当被bool()调用时的行为,应该返回True或者False。

l=[1,2,3,4]
print(l.__len__())  # 4
r=1>2
print(r.__bool__())  # False

    5.3,常用魔法方法(3)

        - __str__(self):定义当被str()调用时的操作。
            默认返回对象信息。
            print对象时会被执行。
            str()用于将值转化为适合人们阅读的形式。
        - __repr(self):定义当被repr()调用时的行为。
            repr()用于将值转化为供解释器读取的形式。

class myclass:
    def __init__(self):
        self.name="Raj"
        self.age=21
    def __str__(self):
        return "name : {} age : {}".format(self.name, self.age)
    def __repr__(self):
        return {"name":self.name, "age":self.age}
obj = myclass()
print(obj.__str__())  # name : Raj age : 21
print(obj.__repr__())  # {'name': 'Raj', 'age': 21}

    5.4,常用魔法方法(4)

        - __getattr__(self,name):定义当用户试图获取一个不存在的属性时的行为。
        - __setattr__(self,name,value):定义当一个属性被设置时的行为。
        - __getattribute__(self,name):定义当该类的属性被访问时的行为。
            访问对象属性或者方法时,首先被调用的方法。

# getattr()
class A():
    a = 5
    def __init__(self,x):
        self.x = x
    def hello(self):
        return "hello func"
a = A(10)
print(getattr(a,"x"))  # a.x,10
print(getattr(a,"y",18))  # a.y,当不存在时返回第三个参数作为默认值,18
print(getattr(a,"hello")())  # a.hello(),hello func
print(getattr(A,"a"))  # A.a,5

# __getattr()__与__getattribute()__
class A(object):
    '''
        从输出结果得知,在获取对象属性时, __getattribute()__ 一定被调用,不管属性存不存在,
        首先都会调用。如果碰到 a.y 这种不存在对象时, __getattribute()__ 会找不到,这时再
        调用 __getattr()__ ,可以通过这个方法设置属性不存在时的默认值。
    '''
    def __init__(self,x):
        self.x=x
    def hello(self):
        return "hello func"
    def __getattr__(self,item):
        print("in __getattr__")
        return 100
    def __getattribute__(self, item):
        print("in __getattribute__")
        return super(A,self).__getattribute__(item)
a = A(10)
print(a.x)
print(a.y)
# 输出结果
# in __getattribute__
# 10
# in __getattribute__
# in __getattr__
# 100

    5.5,Python类中的内置属性

        - __dict__:类的属性(包含一个字典,由类的数据属性组成)。
        - __doc__:类的文档字符串。
        - __name__:类名。
        - __module__:类定义所在的模块
            类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__等于mymod。
        - __bases__:类的所有父类构成元素(包含了一个由所有父类组成的元组)。

# __dict__
class A:
    a = 1
    b = 2
    def __init__(self):
        self.s = "hello world"
print(A.__dict__)
# 输出结果
# {'__module__': '__main__', 'a': 1, 'b': 2, 
# '__init__': <function A.__init__ at 0x0000026F6FE5DF70>,
# '__dict__': <attribute '__dict__' of 'A' objects>,
# '__weakref__': <attribute '__weakref__' of 'A' objects>,
# '__doc__': None}

# __doc__
import string
print(string.__all__)
# ['ascii_letters', 'ascii_lowercase', 'ascii_uppercase',
# 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable',
# 'punctuation', 'whitespace', 'Formatter', 'Template']

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。