• Python学习三(面向对象)


    1.面向对象和面向过程

            面向过程就是所有的事情已过程为主,关注的重点是过程,即第一步、第二步、第三步是什么。C语言就是典型的面向过程的语言。C语言需要只要先找到main函数,在main函数中一步一步的往下执行,比如如下代码:

    1. Print('step1')
    2. print('step2')
    3. print('step3')

            面向对象关注点则是对象。比如一个人是一个对象,这个人身高、体重就是对象的属性,而跑、跳则是这个对象可以执行的相关操作。比如如下代码:

    1. class 类名:
    2. def 方法1();
    3. def 方法2():

            简而言之,编写函数就是“面向过程”编写类就是“面向对象”

    2.类和对象

            对象:具有行为属性。在进行描述的时候,属性多为名字。行为多为动词。

            :指一个类别。具有相同属性和行为的“对象”构成的一个整体。

            类和对象之间的关系:

            类是对象的抽象表现,对象是类的具体表现

            类是设计的蓝图,对象是根据蓝图设计出来的具体产物。

    3.类的定义      

            在Python中,通过class关键字来定义一个类。这个类中可以包含零个多个属性和方法

    1. class 类名:
    2. def 方法1();
    3. def 方法2():

     4.类的实例-对象

            当可以实现一个类之后,就可以通过这个类来实例化一个对象。这个对象包含了这个类的全部属性和方法

    1. class person: #类
    2. def a_name(self): #方法
    3. print('xiaoming')
    4. xiaoming = person() #根据person类实例一个对象
    5. xiaohong = person() #根据person类实例一个对象
    6. zhangsan = person() #根据person类实例一个对象
    7. xiaoming.a_name() #调用对象的方法
    8. xiaohong.a_name() #调用对象的方法
    9. zhangsan.a_name() #调用对象的方法
    10. 结果:
    11. xiaoming
    12. xiaoming
    13. xiaoming

    5.动态增加属性和方法

            很多时候我们需要根据需求给对象添加特殊的属性或方法,而这些属性和方法又不能跟其他对象共用,此时就需要动态来添加属性和方法了。

    1. class person: #类
    2. def a_name(self): #方法
    3. print('xiaoming')
    4. def age(self): #动态增加的方法
    5. print("18")
    6. xiaoming = person() #根据person类实例一个对象
    7. xiaohong = person() #根据person类实例一个对象
    8. zhangsan = person() #根据person类实例一个对象
    9. xiaoming.gender = 'boy' #动态增加属性gender
    10. xiaoming.age = age #动态增加方法age
    11. xiaoming.a_name() #调用对象的方法
    12. xiaohong.a_name() #调用对象的方法
    13. zhangsan.a_name() #调用对象的方法
    14. print(xiaoming.gender)
    15. xiaoming.age(xiaoming)
    16. print(zhangsan.gender)
    17. zhangsan.age(zhangsan)
    18. 结果:
    19. xiaoming
    20. xiaoming
    21. xiaoming
    22. boy
    23. 18
    24. Traceback (most recent call last):
    25. File "d:/python/test_project/test.py", line 37, in
    26. print(zhangsan.gender)
    27. AttributeError: 'person' object has no attribute 'gender'
    28. Traceback (most recent call last):
    29. File "d:/python/test_project/test.py", line 38, in
    30. zhangsan.age()
    31. AttributeError: 'person' object has no attribute 'age'

    6.init(self)函数

            在python的init函数中,init前后各有2个下划线。而Init在每次被调用创建对象时,都会“自动调用”一次。参数self是必不可少的。类中定义的方法,第一个参数是固定的,命名为"self"。

    1. class person: #类
    2. def __init__(self):
    3. print("init")
    4. def a_name(self): #方法
    5. print('xiaoming')
    6. xiaoming = person() #根据person类实例一个对象
    7. xiaohong = person() #根据person类实例一个对象
    8. zhangsan = person() #根据person类实例一个对象
    9. 结果:
    10. init
    11. init
    12. init

    7.传入参数赋值属性

            很多时候,每个对象的属性值都是不相同的,就比如我们上边的代码,创建一个“名字”的方法,但是这个方法打印的内容都是相同的。这样就没有版本区分不同的对象了。所以,我们可以通过传入参数的方式赋值不同的属性值。

    1. class person: #类
    2. def __init__(self,name,age):
    3. self.name = name #属性
    4. self.age = age #属性
    5. def action(self): #方法
    6. print('%s is running,age %d' %(self.name,self.age))
    7. xiaoming = person('xiaoming',18) #根据person类实例一个对象
    8. zhangsan = person('zhangsan',20) #根据person类实例一个对象
    9. xiaoming.action() #对象执行方法
    10. zhangsan.action() #对象执行方法
    11. 结果:
    12. xiaoming is running,age 18
    13. zhangsan is running,age 20

    8.类属性

            类属性与当前类有绑定关系,与当前类创建的对象无关系

            对于类属性可以通过类名进行访问,也可以通过对象进行访问。但是,通过对象进行访问,是“只读”,不能进行修改

            对于实例属性,只能通过创建的对象进行访问不能通过类名进行访问

    1. class person: #类
    2. city = 'beijing' #类属性
    3. def __init__(self,name,age):
    4. self.name = name
    5. self.age = age
    6. def action(self): #方法
    7. print('%s is running,age %d' %(self.name,self.age))
    8. xiaoming = person('xiaoming',18) #根据person类实例一个对象
    9. zhangsan = person('zhangsan',20) #根据person类实例一个对象
    10. print(person.city) #打印类属性
    11. xiaoming.city = 'shanghai' #通过对象修改类属性
    12. print(xiaoming.city) #打印对象类属性
    13. print(person.city) #打印类属性
    14. print(zhangsan.city) #打印对象类属性
    15. print('>>>>>>>>>>>>>>')
    16. person.city = 'nanjing'
    17. print(xiaoming.city) #打印对象类属性
    18. print(person.city) #打印类属性
    19. print(zhangsan.city) #打印对象类属性
    20. 结果:
    21. beijing
    22. shanghai
    23. beijing
    24. beijing
    25. >>>>>>>>>>>>>>
    26. shanghai
    27. nanjing
    28. nanjing

            从上述代码中,通过对象修改了类属性,看似修改成功了,其实并不是修改了类属性,只是动态地给对象创建了一个属性“city”,只不过这个属性名跟类属性的"city"属性名名字相同罢了。

    9.类方法

            类方法需要使用@classmethod修饰

            类方法的第一个参数是固定的,命名为cls

            有两种方式来访问类方法,一种是通过类名来访问,另一种是通过对象名来访问不建议)。

            最好是通过类方法来访问类属性通过实例方法来访问实例属性

    1. class person: #类
    2. city = 'beijing' #类属性
    3. def __init__(self,name,age):
    4. self.name = name
    5. self.age = age
    6. def action(self): #方法
    7. print('%s is running,age %d' %(self.name,self.age))
    8. @classmethod
    9. def move_city(cls,city): #类方法
    10. cls.city = city
    11. xiaoming = person('xiaoming',18) #根据person类实例一个对象
    12. zhangsan = person('zhangsan',20) #根据person类实例一个对象
    13. print(person.city)
    14. person.move_city('shenzhen') #通过类名访问
    15. print(person.city)
    16. xiaoming.move_city("guangzhou") #通过对象名访问
    17. print(person.city)
    18. 结果:
    19. beijing
    20. shenzhen
    21. guangzhou

    10.私有变量(private)

            如果希望类中的属性为私有属性,可以通过在属性名称前加两个下划线__来实现。此时只能通过内部进行访问外部不能访问

    1. class person: #类
    2. city = 'beijing' #类属性
    3. def __init__(self,name,age):
    4. self.__name = name #私有属性
    5. self.__age = age #私有属性
    6. def action(self): #方法
    7. print('%s is running,age %d' %(self.name,self.age))
    8. def get_name(self): #访问私有属性
    9. print(self.__name)
    10. def get_age(self): #访问私有属性
    11. print(self.__age)
    12. xiaoming = person('xiaoming',18) #根据person类实例一个对象
    13. zhangsan = person('zhangsan',20) #根据person类实例一个对象
    14. xiaoming.get_name()
    15. xiaoming.get_age()
    16. 结果:
    17. xiaoming
    18. 18

            如果直接调用实例进行访问的话,则会报错

    1. print(xiaoming.__name)
    2. 结果:
    3. Traceback (most recent call last):
    4. File "d:/python/test_project/test.py", line 38, in
    5. print(xiaoming.__name)
    6. AttributeError: 'person' object has no attribute '__name'

            那为什么要设置私有变量呢?因为这样可以在方法中对传入的参数进行判断,避免无效的参数输入

    1. class person: #类
    2. def __init__(self,name,age):
    3. self.__name = name #私有属性
    4. self.__age = age #私有属性
    5. def set_age(self,s_age):
    6. if not isinstance(s_age,(int)):
    7. raise TypeError('age false type')
    8. if(s_age > 0 and s_age < 100):
    9. self.__age = s_age
    10. print('age %d' %self.__age)
    11. else:
    12. print('age not correct:%d' %s_age)
    13. xiaoming.set_age(18)
    14. xiaoming.set_age(200)
    15. xiaoming.set_age('18')
    16. 结果:
    17. age 18
    18. age not correct:200
    19. Traceback (most recent call last):
    20. File "d:/python/test_project/test.py", line 52, in
    21. xiaoming.set_age('18')
    22. File "d:/python/test_project/test.py", line 29, in set_age
    23. raise TypeError('age false type')
    24. TypeError: age false type

    11.继承

            当有两个属性高度类似的类时,就可以使用继承。如果类A继承了类B,那么A就是子类,B就是父类。子类一旦继承了父类,那么子类就会具备父类的一切特征。因此,父类能做的事情,子类也都可以做。

    1. class fater: #父类
    2. def __init__(self):
    3. self.name = 'fater'
    4. self.age = 58
    5. class child(fater): #子类
    6. def __init__(self):
    7. super().__init__() #调用父类的init方法
    8. self.gender = 'boy'
    9. laowang = fater(); #实例父类
    10. print(laowang.name) #打印父类属性
    11. xiaowang = child(); #实例子类
    12. print(xiaowang.name) #打印子类继承父类的属性
    13. print(xiaowang.gender) #打印子类特有的属性
    14. print(laowang.gender) #打印父类中子类的属性(报错)
    15. 结果:
    16. fater
    17. fater
    18. boy
    19. Traceback (most recent call last):
    20. File "d:/python/test_project/test.py", line 64, in
    21. print(laowang.gender)
    22. AttributeError: 'fater' object has no attribute 'gender'

    12.多重继承

            有时一个对象需要继承多个父类的属性,这就是多重继承。

    1. class fater: #父类
    2. def __init__(self,name,age):#属性
    3. self.name = name
    4. self.age = age
    5. def get_name(self):#方法
    6. print('fater name:%s' %self.name)
    7. class mother: #父类
    8. def __init__(self,name,age) -> None: #属性
    9. self.name = name
    10. self.age = age
    11. def get_name(self):#方法
    12. print('mother name:%s' %self.name)
    13. class child(fater,mother):#子类,按照先后顺序进行继承
    14. def __init__(self, name, age):#属性
    15. super().__init__(name, age) #调用父类的init方法
    16. self.gender = 'boy'
    17. ft = fater('laowang',58); #实例
    18. mt = mother('laohong',55) #实例
    19. kid = child('xiaoming',10) #实例
    20. print(ft.name)
    21. print(mt.name)
    22. print(kid.name) #父类属性
    23. print(kid.age) #父类属性
    24. print(kid.gender) #子类属性
    25. kid.get_name() #父类方法
    26. 结果:
    27. laowang
    28. laohong
    29. xiaoming
    30. 10
    31. boy
    32. fater name:xiaoming

            可以看到,虽然同时继承了father和mother,但是调用父类的"name"方法时,调用的还是fater的方法。因为在继承时,father在前

            那把mother改到前面后试试。

    1. class child(mother,fater):#子类,按照先后顺序进行继承
    2. 结果:
    3. mother name:xiaoming

    13.多态

    1. class fater: #父类
    2. def __init__(self,name,age):#属性
    3. self.name = name
    4. self.age = age
    5. def get_name(self):#方法
    6. print('fater name:%s' %self.name)
    7. class child(fater):#子类
    8. def __init__(self, name, age):#属性
    9. super().__init__(name, age) #调用父类的init方法
    10. self.gender = 'boy'
    11. def get_name(self):
    12. print('child name:%s' %self.name)
    13. ft = fater('laowang',58); #实例
    14. kid = child('xiaoming',10) #实例
    15. kid.get_name()
    16. 结果:
    17. child name:xiaoming

            可以看到,child是从father处继承了属性和方法,child和father有同名的方法get_name,但是当调用child的get_name方法时,会自动调用自身的方法,而不会调用父类的方法。这就是多态。

            对于一个变量,只需要知道父类型,无需确切地知道它的子类型,就可以放心地调用方法,而具体调用的方法是作用在father还是child,由运行时该对象的确切类型决定,这就是多态的威力。调用方只管调用,不管细节,而当需要新增一种子类型是,只要确保方法编写正确,不用管原来的代码是如何调用的。这就是著名的“开闭”原则。

  • 相关阅读:
    在T3开发板上实现SylixOS最小系统(三)
    linux下netlink的使用
    sql 查询
    大数据毕业设计Python+Spark知识图谱高考志愿推荐系统 高考数据分析 高考可视化 高考大数据 计算机毕业设计 机器学习 深度学习 人工智能
    C现代方法(第1&2章)笔记——概述、基本概念
    RabbitMQ(四)
    torch.cuda.is_avaliable()在命令行里是true,pycharm是false【省流:换Pycharm】
    Visual Studio 2019下编译OpenCV 4.7 与OpenCV 4.7 contrib
    STM32的四种开发方式
    [网鼎杯 2020 朱雀组]Nmap 通过nmap写入木马 argcmd过滤实现逃逸
  • 原文地址:https://blog.csdn.net/qq_26226375/article/details/125997706