一、面向对象编程

1.1 面向过程与面向对象

面向过程和面向对象都是一种编程方式,只不过再设计上有区别。

1.1.1 面向过程pop:

举例:孩子上学

1. 妈妈起床

2. 妈妈洗漱

3. 妈妈做饭

4. 妈妈把孩子叫起来

5. 孩子起床

6. 孩子洗漱

7. 孩子吃饭

8. 妈妈给孩子送学校去

最为典型就是我们的C语言编程。

1》导入各种外部库

2》设计各种全局变量

3》写一个函数

4》写一个函数

5》……..

6》写一个main主函数作为程序入口部分

– 面向过程的编程思想将一个功能分解为一个一个小的步骤, 我们通过完成一个一个的小的步骤来完成一个程序

– 这种编程方式,符合我们人类的思维,编写起来相对比较简单

– 但是这种方式编写代码的往往只适用于一个功能, 如果要在实现别的功能,即使功能相差极小,也往往要重新编写代码, 所以它可复用性比较低,并且难于维护

优点:简单直观、性能高效、代码简洁。

缺点:不易维护、不易扩展、代码重用性低。

1.1.2 面向对象oop:

举例:孩子上学

1》妈妈 送 孩子 上学 python、java、C++都是面向对象的编程方式。 以python为例

1》导入各种库

2》设计各种全局变量

3》设计你所需要的类——妈妈类、孩子类

4》main主函数可有可无

– 面向对象的编程思想,将所有的功能统一保存到对应的对象中 比如,妈妈功能保存到妈妈的对象中,孩子的功能保存到孩子对象中 。要使用某个功能,直接找到对应的对象即可

– 这种方式编写的代码,比较容易阅读,并且比较易于维护,容易复用。

– 但是这种方式编写,不太符合常规的思维,编写起来稍微麻烦一点

优点:模块化、安全性高、代码重用性高。

缺点:学习难度大、性能开销大、调试困难。

1.2 类 和 对象

目前我们所学的python中的内置类型都是对象——内置对象,内置对象有时候不能满足我们的需求,需要自定义一些对象。

10, 20, 30, -40, a=10, b=20等等等,都是整数,对其进行抽象——int类。

python 中一切都是对象。

类也是一个对象。

1.2.1 类的定义 与 实例化对象

语法格式1:
class ClassA:
    # 公共的属性
    def __init__(self):
        pass
    def fun1(self):
        pass
    def fun2(self):
        pass

语法格式2:
class ClassA(object):
    # 公共的属性
    def __init__(self):
        pass
    def fun1(self):
        pass
    def fun2(self):
        pass
        
 实例化对象的语法:
 1》无参
     对象名 = 类名()
 2》有参
     对象名 = 类名(参数列表)                                     

例举 

# 设计类
class student:
    name = None
    age = None
    gander = None
# 创建对象
student1 = student()
# 给对象赋值
student1.name = '小明'
student1.age = 18
student1.gender = '男'
# 获取对象中的信息
print(student1.name,student1.age,student1.gander)

1.2.2 访问属性/方法

使用符号 . 进行访问

# 访问属性

对象名.属性

# 访问方法

对象名.方法名()

1.2.3 对象与类的关系【1】

  1. 对象拥有类的所有属性和方法
  2. 对象的属性和方法可以单独添加、删除、修改
  3. 对象与对象之间的属性和方法不可共享
  4. 对象不能独自创建,必须依托于类,类可以实例化N个对象
#创建一个闹钟类
class clock:
    id = None
    price = None
    def ring(self):
        import winsound #python内置模块是让电脑响    
        winsound.Beep(2000,3000)#频率和时间
        print(f'电脑编号{self.id},电脑价格{self.price}')
#闹钟1
clock1 = clock()
clock1.id =12344
clock1.price = 19.99
clock1.ring()

#闹钟2
clock2 = clock()
clock2.id = 12345
clock2.price = 29.99
clock2.ring()

1.2.3 对象与类的关系【2】

from types import MethodType


class student:
    def __init__(self,name):
        self.name = name

    def fun1(self):
        print(f'{self.name}会唱歌')

s1 = student('刘')
s2 = student('坤哥')

s1.fun1()#刘会唱歌
s2.fun1()#坤哥会唱歌

def Ctrl(self):
    print(f'{self.name}会穿背带裤打篮球')

s2.Ctrl=MethodType(Ctrl,s2)

s2.Ctrl()#坤哥会穿背带裤打篮球
还可以使用以下函数的方式来访问属性:
  • getattr(obj, name[, default]) : 访问对象的属性。
  • hasattr(obj,name) : 检查是否存在一个属性。
  • setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
  • delattr(obj, name) : 删除属性。
  • 1.2.5 魔方方法——构造函数 与 析构函数

    1. __init__ 构造函数:完成对象的初始化工作,方便统一管理、调用类创建对象时,自动执行。
    2. __del__ 析构函数:删除对象时执行一些操作,自动执行。
    3. __str__ 打印方法:输出执行信息,自动执行。
    class Animal:
        #构造函数
        def __init__(self,name,call):
            self.name = name
            self.call = call
    
        #打印方法
        def __str__(self):
            return f'{self.call},你在{self.name}叫什么'
    
        #析构函数
        def __del__(self):
            print(f"{self.name}消音成功")
    
    dog = Animal('狗','汪汪汪')
    cat = Animal('猫','喵喵喵')
    
    print(dog)
    print(cat)
    """
    汪汪汪,你在狗叫什么
    喵喵喵,你在猫叫什么
    狗消音成功
    猫消音成功
    """

    1.2.6 类属性/方法 与 实例对象属性/方法 与 静态方法

    class Bank(object):
        """
        定义了一个银行卡类,用于初始化、存钱、取钱
        """
        total_money = 0
    
        def __init__(self, name, money):
            self.name = name
            Bank.total_money += money    #改为self.
    
        def save(self, money):
            Bank.total_money += money
    
        def draw(self, money):
            Bank.total_money -= money
    
    b1 = Bank('张三', 1000)
    print(b1.total_money)
    b1.save(5000)
    print(b1.total_money)
    b1.draw(3000)
    print(b1.total_money)
    
    b2 = Bank('李四', 8888)
    print(b2.total_money)
    b2.save(10000)
    print(b2.total_money)
    类方法、实例方法、静态方法
    class student:
        #定义一个学生类
        grade = 'py24101'
    
        @classmethod
        def clas_fun(cls):
            """类方法中只能调用类属性和类方法"""
            print(cls.grade)
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def fun1(self):
            """实例方法中能调用类属性、实例属性"""
            print(f"实例方法中输出类属性{self.grade}, 输出实例属性{self.name}")
    
        @staticmethod
        def sta_fun(x):
            print(f"{x}静态方法一般实现与类和对象无关联的操作,例如:游戏说明书等")
    
    s1 = student('小明',18)
    #调用类方法
    #方法一
    student.clas_fun()#py24101
    #方法二
    s1.clas_fun()#py24101
    
    #如何调用实例对象
    #方法一
    student.fun1(s1)#实例方法中输出类属性py24101, 输出实例属性小明
    #方法二
    s1.fun1() #实例方法中输出类属性py24101, 输出实例属性小明
    
    # 如何调用静态变量
    #方法一
    student.sta_fun(2)#2静态方法一般实现与类和对象无关联的操作,例如:游戏说明书等
    #方法二
    s1.sta_fun(2) #2静态方法一般实现与类和对象无关联的操作,例如:游戏说明书等
    

    1.2.7 Python的内置类属性

  • __dict__ : 类的属性(包含一个字典,由类的数据属性组成)
  • __doc__ :类的文档字符串
  • __name__: 类名
  • __module__: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
  • __bases__ : 类的所有父类构成元素(包含了一个由所有父类组成的元组)
  • class Student(object):
        """
        定义一个学生类
        属性:名字 年龄
        方法:method_1 method_2
        """
        name = '张三'
        age = 18
    
        def method_1(self):
            pass
    
        def method_2(self):
            pass
    
    print(Student.__dict__)
    print(Student.__doc__)
    print(Student.__name__)
    print(Student.__module__)
    print(int.__module__)
    print(Student.__bases__)
    """
    {'__module__': '__main__', '__doc__': '\n    定义一个学生类\n    属性:名字 年龄\n    方法:method_1 method_2\n    ', 'name': '张三', 'age': 18, 'method_1': <function Student.method_1 at 0x0000023EBF1A4AE0>, 'method_2': <function Student.method_2 at 0x0000023EBF1A4C20>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>}
    
        定义一个学生类
        属性:名字 年龄
        方法:method_1 method_2
        
    Student
    __main__
    builtins
    (<class 'object'>,)
    """

    1.3 类的封装【私有属性与方法】

    封装是类的三大特性之一。

    封装指的是隐藏对象中一些不希望让外部所访问的属性或方法。

    python中封装其实是通过设置访问权限来体现的,私有属性和私有方法是控制访问权限的组成部分。

    1.3.1 私有属性

    在类的内部使用,不希望外部直接访问的变量。

    在python中,使用双下划线作为前缀来定义私有属性。

    私有属性在类外不能访问

    class bank:
        def __init__(self,name,pwd):
            self.name = name
            self.__pwd = pwd
            # 为了在某些需要的时候,访问到私有属性,所以需要在类内部设置两个接口
    
        def get_pwd(self):
            return self.__pwd
    
        def set_pwd(self,newpwd):
            self.__pwd = newpwd
    
    user = bank("小明",'123456')
    
    print(user.name)#小明
    # print(user.__pwd) 会报错
    print(user.get_pwd())#123456
    user.set_pwd('456789')
    print(user.get_pwd()) #456789

    1.3.2 私有方法

    和私有属性是一样的。

    class Bank(object):
        """
        定义了一个银行卡类
        属性:name     pwd密码【我不希望外部访问】
        """
        def __init__(self, name, pwd):
            self.name = name
            self.__pwd = pwd
    
        def __info(self):
            print(f"名字{self.name}, 密码{self.__pwd}")
    
        def get_info(self):
            self.__info()
    
    # Bank.__info() 报错
    b1 = Bank('李四', '123456')
    # b1.__info()   报错
    b1.get_info()

    1.3.3 属性装饰器

    属性装饰器是实现把方法转为属性的装饰器。

    作用:

    1. 把方法转为属性,便于操作属性
    2. 实现对属性的更改(验证)、查看、删除

    class 类名:

            def __init__(self,name):

                    self.name = name

            @property

            def 函数名(self):

                    return self.name

            @函数名.setter

            def 函数名(self,m)

                    self.name +=m

             

    class bank:
        def __init__(self,name ='',money = 0): #可以在里面定义初始值
            self.name = name
            self.__money = money
    
        @property
        def my_money(self):
            return self.__money
    
        @my_money.setter
        def my_money(self,m):
            self.__money+=m
    
    user = bank('小明',1000)
    
    user.my_money = 900
    print(user.my_money) #1900
    

    1.4 类的继承

    面向对象的编程带来的主要好处之一就是代码的重用,实现这种重用的方法之一就是通过继承机制。

    通过继承创建的新类称之为【子类】或者【派生类】,被继承的类称之为【父类】、【基类】、【超类】。

    1.4.1 继承语法格式

    class 子类名(父类名列表):

            pass

    class Parent(object):
        """
        定义父类
        """
        par_attr = 100
    
        def __init__(self):
            print("初始化父类")
    
        def par_fun1(self):
            print("父类方法1")
    
        def par_fun2(self):
            print("父类方法2")
    
    class Child(Parent):
        """
        定义子类
        """
        child_attr = 666
        def __init__(self):
            print("初始化子类")
    
        def child_fun1(self):
            print("子类方法1")
    
    c1 = Child()
    print(c1.child_attr)
    c1.child_fun1()
    
    print(c1.par_attr)
    c1.par_fun1()
    c1.par_fun2()

    1.4.2 多继承语法【明白即可,不建议乱用】

    如果在继承的元组()里面有一个以上的类,就称之为多继承

    class a:
        pass
    class b:
        pass
    class c:
        pass
    class d(a,b,c):
        pass
    
    D = d()
    print(d.mro())#[<class '__main__.d'>, <class '__main__.a'>, <class '__main__.b'>, <class '__main__.c'>, <class 'object'>] 查顺序
    print(d.__bases__) #(<class '__main__.a'>, <class '__main__.b'>, <class '__main__.c'>)查父类
    
    

    1.4.3 继承重写父类方法

    如果你的父类方法不能满足你得要求,你可以在之类中重写父类的方法。

    # 重写
    class Parent(object):
        def method(self):
            print(f"{self}的方法")
    
    class Child(Parent):
        def method(self):
            print("xxxxxxxxxx")
            print(f"子类重写父类ri{self}的方法")
    
    c = Child()
    c.method()

     这里列出了一些通用的功能,可以在自己的类重写:

    __init__ ( self [,args…] )构造函数

    简单的调用方法: obj = className(args)

    __del__( self ) 析构方法

    简单的调用方法 : del obj

    __repr__( self ) 转化为供解释器读取的形式

    简单的调用方法 : repr(obj)

    __str__( self ) 用于将值转化为适于人阅读的形式

    简单的调用方法 : str(obj)

    __cmp__ ( self, x ) 对象比较

    简单的调用方法 : cmp(obj, x)

    1.4.4 python继承特点

  • 在子类中如果需要父类的构造方法,需要显式调用父类的构造方法,或者不重写父类的构造方法。__init__()
  • 在子类中调用父类的方法,需要显式调用,且第一个参数self不能省略
  • 不重写父类构造方法 
    class father:
        def __init__(self,x,y):
            self.x = x
            self.y = y
    
        def sum(self):
            print(f'{self.x},{self.y}')
    
    class child(father):
        def fun(self):
            print(f'{self.x},{self.y}')
    
    stu = child(1,2)
    stu.fun() #1,2

    重写父类构造方法、里面显式调用父类构造方法
    class father:
        def __init__(self,x,y):
            self.x = x
            self.y = y
    
    class child(father):
        def __init__(self,x,y,z):
            father.__init__(self,x,y)
            self.z = z
        def fun(self):
            print(self.x,self.y,self.z)
    stu = child(1,2,3)
    stu.fun() #1,2,3
    

    用super().方法/成员变量
    class father:
        def __init__(self,x,y):
            self.x = x
            self.y = y
    
    class child(father):
        def __init__(self,x,y,z):
            super().__init__(x,y)
            self.z = z
        def fun(self):
            print(self.x,self.y,self.z)
    stu = child(1,2,3)
    stu.fun() #1,2,3
    

    1.4.5 运算符重载

    在Python中,并没有像其他语言(如C++)中那样的内置机制来重载运算符。但是,你可以通过定义特定的方法来模拟运算符重载的行为。

    以下是一些常见运算符以及它们对应的特殊方法:

    加法:+ 对应 __add__

    减法:- 对应 __sub__

    乘法:* 对应 __mul__

    除法:/ 对应 __truediv__

    取模:% 对应 __mod__

    幂运算:** 对应 __pow__

    位运算:

    位运算:>> 对应 __rshift__

    位运算:& 对应 __and__

    位运算:| 对应 __or__

    位运算:^ 对应 __xor__

    class a:
        def __init__(self,x):
            self.x = x
        def __add__(self, other):
            return self.x + other.x
    b = a(3)
    c = a(4)
    print(b+c) #7
    
    
    class d:
        def __init__(self,x,y):
            self.x = x
            self.y = y
        def __add__(self, other):
            return self.x*other.y+self.y*other.x
    
    e = d(2,3)
    f = d(4,5)
    print(e+f)#22
    

    1.5 类的多态

    python中的多态也可以通过方法重写进行。

    同一个方法,不同对象显式的结果不同

     class Animal:
        def speak(self):
            pass
    class Dog(Animal):
        def speak(self):
            print('汪汪汪')
    class Cat(Animal):
        def speak(self):
            print('喵喵喵')
    
    def Animal_speak(animal:Animal):
        animal.speak()
    
    dog = Dog()
    cat = Cat()
    
    Animal_speak(dog)#汪汪汪
    Animal_speak(cat)#喵喵喵

    1.创建学生类Person。

    2.添加静态方法,showInfo:

    (1)显示信息“龙的传人”;

    3.添加类属性:country,国籍,默认值为“中国“。

    4.添加类属性:nation,民族,默认值为“汉族“。

    5.添加构造方法,添加如下对象属性:

    (1)name,保存学生姓名,默认值为空字符串。

    (2)age,保存学生年龄,默认值为0。

    (3)birth,保存出生日期,默认值为空字符串。

    (4)money,保存工资收入,私有权限,默认值为0。

    6.添加类方法,获取两个类属性的值。

    7.添加魔法方法,将所有属性用格式化字符串组合成一个字符串后返回。

    (1)格式如下: 国籍:中国 民族:汉 姓名:XXX 年龄:XXX 出生日期:XXX

    8.添加setName方法,修改对象属性name。

    9.添加getName方法,获得对象属性name的值。

    10.添加返回age值的方法getAge,利用属性装饰器修饰该方法,并对age值进行修改。 11.添加setBirth方法,修改对象属性birth。

    12.添加getBirth方法,获得对象属性birth的值。

    13.添加私有属性money的set和get方法。

    14.添加对象方法info,输出当前对象的个人信息:

    (1)格式如下:姓名—年龄—出生日期—存款

    15.添加主程序入口,完成如下任务:

    (1)调用静态方法: ①提示:通过对象调用 ②提示:通过类名调用;

    (2)创建一个对象。

    (3)修改对象的所有对象属性。

    (4)通过对象方法获得对象的所有属性值,并显示。

    (5)调用info显示对象信息。

    (6)调用对象的打印方法,输出信息;

    (7)再次修改所有对象的属性。

    (8)再次调用对象的打印方法。

    from tkinter.font import names
    
    
    class Person:
        country = '中国'
        nation = '汉族'
    
        @staticmethod
        def showInfo():
            print('龙的传人')
    
        def __init__(self,name = '',age = 0,birth = '',money = 0):
            self.name = name
            self.age = age
            self.birth = birth
            self.__money = money
    
        @classmethod
        def func(cls):
            print(cls.country,cls.nation)
    
        def __str__(self):
            return f' 国籍:{self.country} \n 民族:{self.nation} \n 姓名:{self.name} \n 年龄:{self.age} \n 出生日期:{self.birth}'
    
        def setName(self,name):
            self.name = name
    
        def getName(self):
            print(self.name)
    
        @property
        def getAge(self):
            return self.age
        @getAge.setter
        def getAge(self,newage):
            self.age = newage
    
        def setBirth(self):
            return self.birth
        def getBirth(self,birth):
            self.birth = birth
    
        def set_money(self):
            return self.__money
        def get_money(self,money):
            self.__money = money
    
        def info(self):
            print(f'姓名:{self.name} 年龄:{self.age} 出生日期:{self.birth} 存款:{self.__money}')
    
    
    user = Person()
    user.showInfo()
    user.setName("张三")
    user.getAge = 25
    user.getBirth('1999-09-30')
    user.get_money(20000)
    user.info()
    print(user)
    user.setName('小明')
    user.getAge = 19
    user.getBirth('2005-07-30')
    user.get_money(2000)
    print(user)
    

    作者:小成晓程

    物联沃分享整理
    物联沃-IOTWORD物联网 » python——面向对象

    发表回复