zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Python中的面向对象编程(类编程)由简单到复杂的示例代码

Python编程代码 简单 示例 复杂 面向对象编程
2023-09-11 14:15:39 时间

关于本文代码中的self的含义,大家可参考下面这篇博文:
https://blog.csdn.net/wenhao_ir/article/details/125384347

另:说明一下,本博文中“成员函数”的意思和“方法”的意思一样。

01-最简单的Python面向对象编程(类编程)示例代码

class Fruit:
    color = 'red'

    def taste(self):
        return 'delicious'


apple = Fruit()
a_character = apple.color
b_character = apple.taste()

print('\na_character:{}'.format(a_character))
print('b_character:{}'.format(b_character))

运行结果如下图所示:
在这里插入图片描述

02-类中的成员函数引用类的成员变量的情况

class Staff:  # Staff为员工的意思
    bonus = 30000  # bonus为津贴、奖金的意思

    def salary(self):  # salary为工资的意思
        salary = 10000+self.bonus
        return salary


zhang_san = Staff()
zhang_san_salray = zhang_san.salary()

运行结果如下所示:
在这里插入图片描述

03-带构造函数(初始化函数)的情况

class Staff:  # Staff为员工的意思
    def __init__(self, bonus):  # bonus为津贴、奖金的意思
        self.bonus = bonus

    def salary(self):  # salary为工资的意思
        salary = 10000+self.bonus
        return salary


zhang_san = Staff(3000)
zhang_san_salray = zhang_san.salary()

运行结果如下:
在这里插入图片描述

04-成员函数带参数(不包括构造函数)

class AnimalBaseClass:
    def __init__(self, num):
        self.animallegs = num
        self.head_num = 0

    def walk(self):
        print('走')

    def cry(self):
        print('叫')

    def get_legs_num(self):
        print(self.animallegs)

    def input_head_num(self, num2):
        self.head_num = num2

    def get_head_num(self):
        print(self.head_num)


animal = AnimalBaseClass(4)
animal.input_head_num(1)

animal.get_legs_num()
animal.get_head_num()

上面的代码中,成员函数input_head_num()是带了参数的。
运行结果如下:
在这里插入图片描述

05-方法调用方法的情况

示例代码如下:

class A(object):
    bar = 1

    def func1(self):
        print('foo')

    def func2(self):
        print('func2')
        print(self.bar)
        self.func1()  # 调用方法func1()


a1 = A()
a1.func2()

运行结果如下:
在这里插入图片描述

06-类的继承(父类与子类)

class AnimalBaseClass:
    def __init__(self, num):
        self.animallegs = num

    def walk(self):
        print('走')

    def cry(self):
        print('叫')

    def get_legs_num(self):
        print(self.animallegs)


class BirdClass(AnimalBaseClass):
    head_num = 1

    def cry(self):
        print('吱吱叫')

    def run(self):
        print('跑')

    def get_head_num(self):
        print(self.head_num)


piyo_suke = BirdClass(2)
piyo_suke.cry()
piyo_suke.run()
piyo_suke.get_legs_num()
piyo_suke.get_head_num()

在上面的代码中,类BirdClass继承于类AnimalBaseClass,它拥有类AnimalBaseClass的变量和成员函数。
运行结果如下:
在这里插入图片描述
当父类和子类都拥有同样名称的成员函数时,子类调用这个成员函数时会优先调用子类中成员函数,这个功能叫重写(覆盖),英文中的叫法叫“override”所以上面的代码中语句

piyo_suke.cry()

的运行结果为“吱吱叫”,而不是“叫”。
不仅是一般的成员函数能被改写,构造函数也可以在子类中重写,比如下面的代码:

class AnimalBaseClass:
    def __init__(self, num):
        self.animallegs = num

    def walk(self):
        print('走')

    def cry(self):
        print('叫')

    def get_legs_num(self):
        print(self.animallegs)


class BirdClass(AnimalBaseClass):
    def __init__(self, num1, num2):
        self.animallegs = num1
        self.head_num = num2

    def cry(self):
        print('吱吱叫')

    def run(self):
        print('跑')

    def get_head_num(self):
        print(self.head_num)


piyo_suke = BirdClass(3, 1)
piyo_suke.cry()
piyo_suke.run()
piyo_suke.get_legs_num()
piyo_suke.get_head_num()

上面的代码中,子类BirdClass的构造函数和父类AnimalBaseClass不一样。
运行结果如下:
在这里插入图片描述
要注意,你的代码中用到了哪些成员变量,你在构造函数就要注意把它初始化,否则调用时会出错,比如下面这样写就不行:

class BirdClass(AnimalBaseClass):
    def __init__(self, num2):
        self.head_num = num2

    def cry(self):
        print('吱吱叫')

    def run(self):
        print('跑')

    def get_head_num(self):
        print(self.head_num)


piyo_suke = BirdClass(1)
piyo_suke.cry()
piyo_suke.run()
piyo_suke.get_legs_num()
piyo_suke.get_head_num()

上面的代码中,成员函数get_legs_num()用到了成员变量animallegs,但是没有进行初始化,所以在调用语句piyo_suke.get_legs_num()时会报下面这样的错:
在这里插入图片描述

06-附1-在类的定义中调用父类的方法

示例代码如下:

class A:
    def __init__(self):
        print('Enter A')

    def fun1(self, a, b):
        print('fun1的结果为{}'.format((a+b)))


class B(A):
    def __init__(self):
        print('Enter B')
        self.x = 100
        self.y = 88

    def fun2(self):
        A.fun1(self, self.x, self.y)


object1 = B()
object1.fun2()

运行结果如下:
在这里插入图片描述
在上面的代码中,B类为A的子类,在B类的方法fun2()中,调用了其父类A中的方法fun1(),注意,此时第一个参数self要写上,即语句:

A.fun1(self, self.x, self.y)

不能写成:

A.fun1(self.x, self.y)

更高级的关于类的定义中调用父类的方法【使用内置函数super()】,请参阅我的另一篇博文 https://blog.csdn.net/wenhao_ir/article/details/125472478

07-使用修饰符classmethod定义不需要实例化对象就能调用的方法

classmethod 修饰符对应的方法第一个参数我们通常不取名为self,而取名为cls。关于类的方法的第一参数的详解,见我的另一篇博文https://blog.csdn.net/wenhao_ir/article/details/125384347
这样的方法通常用来输出类的一些属性信息等,或者执行一些不需要初始化值的功能等。

示例代码如下:

class A(object):
    bar = 1

    def func1(self):
        print('foo')

    @classmethod
    def func2(cls):
        print('func2')
        print(cls.bar)
        cls().func1()  # 调用方法func1()


A.func2()  # 方法func2不需要实例化即可被调用

运行结果如下:
在这里插入图片描述
注意:上面代码中的语句:

cls().func1()

不能像需要实例化的方法那样写成:

cls.func1()

cls()相当于还是在执行func2()时临时产生了一个对象。

08-使用修饰符staticmethod声明一个静态方法(调用时无需传参数,不用实例化即可被调用)

示例代码如下:

class MyClass(object):
    @staticmethod  # 使用修饰符staticmethod声明一个静态方法
    def f1():
        print('My name is SuWenhao')


MyClass.f1()  # 静态方法无需实例化即可调用

obj1 = MyClass()
obj1.f1()        # 静态方法也可实例化后调用

运行结果如下:
在这里插入图片描述

09-使用修饰符property将方法变为变量的方式调用

示例代码如下:

class A:
    def __init__(self):
        print('Enter A')
        self.name = 'admin'
        self.pwd = '123456'

    @property
    def fun1(self):
        print("当前的用户名:{0},密码:{1}".format(self.name, self.pwd))


a1 = A()
a1.fun1

运行结果如下:
在这里插入图片描述
分析:在上面的示例代码中,方法fun1()被修饰符property修饰,从而使这个方法的调用变为变量方式的调用。
什么叫变量方式的调用?
先来看正常方式的调用,方法fun1()的正常调用语句如下:

a1.fun1()

变量方式的调用如下:

a1.fun1

可见区别就在于正常方式有括号,而变量方式调用没有括号。
总结一下:对于方法fun1(),如果没有被修饰符property修饰,则应该按下面的方式调用:

a1.fun1()

如果被修饰符property修饰,则应该按下面的方式调用:

a1.fun1

一些与代码规范化相关的建议

在代码的书写格式上注意以下几点(非必须,但是这样书写出来的代码漂亮好看且规范):

  • 成员变量与成员函数之间要有一个空行;
  • 成员函数与成员函数之间要有一个空行;
  • 类与主体代码之间要有两个空行;
  • 类与类之间也要有个两个空行;
  • 类名用驼峰法命名(关于命名规则,可参考博文 https://blog.csdn.net/wenhao_ir/article/details/123117194);