python-面向对象

python-面向对象

1,编程范式

  • 面向对象编程实际上就是一种编程范式。
  • 编程是程序员用 特定的语法 + 数据结构 + 算法 组成的代码来告诉计算机如何执行任务的过程。
  • 两种最重要的编程范式分别是

     面向过程编程

    面向对象编程

2,面向过程编程

  面向过程:核心是过程二字,过程指的是解决问题的步骤,相当于设计一条流水线,机械式的一种思维方式

   优点:复杂的问题流程化,进而简单化

  缺点:可拓展性差,如果要修改,牵一发动全身

"""实现一个用户注册功能"""
# 1.用户输入
# 2.验证是否符合标准
# 3.注册


def enter():
    username = input('请输入用户名>:').strip()
    password = input('请输入密码>:').strip()
    return {
        'username': username,
        'password': password
            }


def check(user_info):
    is_valid = True
    if len(user_info['username']) == 0:
        print('用户名不能为空')
        is_valid = False
    if len(user_info['password']) < 6:
        print('密码不能少于6个字符')
        is_valid = False
    return {
        'is_valid': is_valid,
        'user_info': user_info
    }


def register(check_info):
    if check_info['is_valid']:
        import json
        with open('users.txt', 'w', encoding='utf-8') as f:
            json.dump(check_info['user_info'], f)
        print('注册成功')


def main():
    user_info = enter()
    check_info = check(user_info)
    register(check_info)


if __name__ == '__main__':
    main()

  

  如果添加一个邮箱验证的新功能,牵一发动全身,基本上都需要修改功能:

3,面向对象编程

  面向对象:核心是对象

    对象是特征与技能的结合体    

    优点:可拓展性高

    缺点:编程复杂度高

    应用场景:用户需求经常变化,互联网应用,游戏,企业内部应用。

  面向对象的三大特性

    封装: 如何组织类或模块,让封装的类或组件,尽量只负责一个领域的工作.

    继承: 复用方式之一,概念形成统一。通过继承可以管理多个概念

    多态: 类、方法等的行为不同的做法。目标一致,实现的方式不同

python中一切皆对象

  而在python3中统一了类与类型的概念(类型就是类)

    即便是对于列表,列表也是一个类,也可以调用类下面的函数

l1 = [1, 2, 3]  # l = list[1, 2, 3]
l2 = []
l1.append(4)  
# == list.append(l1, 4)  实际上就相当于list下面调用类的函数(append),
#把l1当作第一个参数传进来,把4当作第二个参数传进来
print(l1)

# 类下面(list是一个类),有很多的功能来给对象使用,但是一般我们不会调用list.append(l1, 4)来
# 传入对象和参数,我们会调用自己,更明确,更简单一点

4,定义类与实例化出对象

   类就是一系列对象相似的特征与技能的结合体。类别,分类。

    (特征:变量,技能:函数;实际上类内部就是变量定义和函数定义)

      作用:进一步提升函数的复用性,拓展性。面向对象,贴近人的思想。

  注意:站在不同的角度,得到的分类是不一样的。

  在现实世界当中:一定先有对象,后有类。

  在程序中:一定得先定义类,后调用类来产生对象。

     站在认类的角度定义类和对象

站在学生的角度,大家都是学生

在现实世界中:
    对象1:张三
        特征:
            学校='school'
            名字='张三'
            性别='女'
            年龄=18
        技能:
            学习
            吃饭
            睡觉
    对象2:李四
        特征:
            学校='school'
            名字='李四'
            性别='男'
            年龄=28
        技能:
            学习
            吃饭
            睡觉
    对象3:王五
        特征:
            学校='school'
            名字='王五'
            性别='女'
            年龄=38
        技能:
            学习
            吃饭
            睡觉


总结现实中学生的学生类
    相似的特征:
        学校=’school‘

    相似的技能
        学习
        吃饭
        睡觉

  站在程序的角度定义类和对象

# 先定义类
class Student:
    school = 'School'

    def learning(self):
        print('is learning')

    def eating(self):
        print('is eating')

    def sleep(self):
        print('is sleeping')

# 后产生对象
stu1 = Student()
stu2 = Student()
stu3 = Student()
print(stu1)
print(stu2)
print(stu3)

  运行结果

<__main__.Student object at 0x0315C490>
<__main__.Student object at 0x0315C8D0>
<__main__.Student object at 0x0315C970>

# 我们可以得到学生对象和对应的地址

5,如何使用类

  先定义类

# 先定义类
class Student:
    school = 'School'  # 数据属性

    def learning(self):  # 函数属性
        print('is learning')

    def eating(self):  # 函数属性
        print('is eating')

    def sleep(self):  # 函数属性
        print('is sleeping')

 1,查看类的名称空间

# 查看类的名称空间:
print(Student.__dict__)
print(Student.__dict__['school'])
print(Student.__dict__['learning'])

  运行结果

{'__module__': '__main__', 'school': 'School', 'learning': <function Student.learning at 0x0309A390>, 'eating': <function Student.eating at 0x0309A3D8>, 'sleep': <function Student.sleep at 0x0309A420>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}

School

<function Student.learning at 0x0309A390>

 2,查看属性

# 查看属性
print(Student.school)  # ==print(Student.__dict__['school'])
print(Student.learning)  # ==print(Student.__dict__['learning'])
print(Student.eating)  # ==print(Student.__dict__['eating'])

  运行结果

School
<function Student.learning at 0x0309A390>
<function Student.eating at 0x0309A3D8>

 3,增加属性

# 增加属性
Student.country = 'China'
print(Student.__dict__)
print(Student.country)

 运行结果

{'__module__': '__main__', 'school': 'School', 'learning': <function Student.learning at 0x0309A390>, 'eating': <function Student.eating at 0x0309A3D8>, 'sleep': <function Student.sleep at 0x0309A420>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None, 'country': 'China'}

China

 4,删除属性

# 删除属性
del Student.country
print(Student.__dict__)

 运行结果

{'__module__': '__main__', 'school': 'School', 'learning': <function Student.learning at 0x0309A390>, 'eating': <function Student.eating at 0x0309A3D8>, 'sleep': <function Student.sleep at 0x0309A420>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}

 5,改属性

# 改属性
Student.school = 'School*'
print(Student.__dict__)

 运行结果

{'__module__': '__main__', 'school': 'School*', 'learning': <function Student.learning at 0x0309A390>, 'eating': <function Student.eating at 0x0309A3D8>, 'sleep': <function Student.sleep at 0x0309A420>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}

 类的第一用途是对类进行操作,第二大用途是实例化产生一个一个的对象

 6,如何使用对象(__init__方法)

   通过 __init__ 方法用来为对象定制对象自己独有的特征

class Student:
    school = 'School'
               # stu1,'王二丫', '女', 18
    def __init__(self, name, sex, age):
        self.Name = name
        self.Sex = sex
        self.Age = age

        # stu1.Name = '王二丫'
        # stu1.Sex = '女'
        # stu1.Age = 18

    def learning(self):
        print('is learning')

    def eating(self):
        print('is eating')

    def sleep(self):
        print('is sleeping')

# 后产生对象
stu1 = Student('王二丫', '女', 18)  # Student.__init__(stu1,'王二丫', '女', 18)

# 加上__init__方法后,实例化的步骤
# 1,先产生一个空对象
# 2,触发方法Student.__init__(stu1,'王二丫', '女', 18)(这就是一个函数)
print(Student.__init__)

# 先产生一个叫stu1的空对象,然后将stu1,加上后面三个参数组成四个参数传给__init__

###
<function Student.__init__ at 0x01DE9390>

 1,查看属性

# 查看属性
print(stu1.__dict__)  # 上面定义好了以后将产生一个名称空间,将这些参数传到里面,形成一个字典
print(stu1.Name)

###
{'Name': '王二丫', 'Sex': '女', 'Age': 18}
王二丫

 2,改属性

# 改属性
stu1.Name = '王二麻'
print(stu1.Name)

###
王二麻

 3,增加属性

# 增加属性
stu1.Friend = '李二麻'
print(stu1.__dict__)

###
{'Name': '王二麻', 'Sex': '女', 'Age': 18, 'Friend': '李二麻'}

 4,删属性

# 删属性
del stu1.Friend
print(stu1.__dict__)

###
{'Name': '王二麻', 'Sex': '女', 'Age': 18}

  

stu2 = Student('李三炮', '男', 38)
print(stu2.Name)
print(stu2.Sex)
print(stu2.Age)

###
李三炮
男
38

7,属性查找与绑定方法

   对象:特征与技能的结合体

  类:类是一系列对象相似的特征与技能的结合体

class Student:
    school = 'School'
               # stu1,'王二丫', '女', 18
    def __init__(self, name, sex, age):
        self.Name = name
        self.Sex = sex
        self.Age = age

        # stu1.Name = '王二丫'
        # stu1.Sex = '女'
        # stu1.Age = 18

    def learning(self):
        print('%s is learning ' % self.Name)

    def eating(self):
        print('%s is eating' % self.Name)

    def sleep(self):
        print('%s is sleeping' % self.Name)

# 后产生对象
stu1 = Student('王二丫', '女', 18)
stu2 = Student('李三炮', '男', 38)
stu3 = Student('张铁蛋', '男', 48)
print(stu1.__dict__)
print(stu2.__dict__)
print(stu3.__dict__)

###
{'Name': '王二丫', 'Sex': '女', 'Age': 18}
{'Name': '李三炮', 'Sex': '男', 'Age': 38}
{'Name': '张铁蛋', 'Sex': '男', 'Age': 48}

 1,类中的数据属性

   类中的数据属性:是所有对象共有的。

# 类中的数据属性:是所有对象共有的
print(Student.school, id(Student.school))

print(stu1.school, id(stu1.school))
print(stu2.school, id(stu2.school))
print(stu3.school, id(stu3.school))

###
School 17292672
School 17292672
School 17292672
School 17292672

 2,类中的函数属性

  类中的函数属性:是绑定给对象使用的,绑定到不同的对象是不同的绑定方法,对象调用绑定方法时,会把对象本身当第一个参数传入(传给self)

# 类中的函数属性:是绑定给对象使用的,绑定到不同的对象是不同的绑定方法,对象调用绑定方法时,会把对象本身当第一个参数传入(传给self)
print(Student.learning(stu1))
print(Student.learning(stu2))
print(Student.learning(stu3))

print(Student.learning)
print(stu1.learning)  # 这里绑定方法还是learning函数,后面跟上它的内存地址,也可以调用
print(stu2.learning)
print(stu3.learning)
stu1.learning()  #把对象本身当第一个参数传给self

###
王二丫 is learning 
None
李三炮 is learning 
None
张铁蛋 is learning 
None
<function Student.learning at 0x0115A420>
<bound method Student.learning of <__main__.Student object at 0x0358C8D0>>
<bound method Student.learning of <__main__.Student object at 0x0358C8F0>>
<bound method Student.learning of <__main__.Student object at 0x0358C950>>
王二丫 is learning 

  当对象在访问一个属性的时候,会先从自己的名称空间里面去找,然后去类里面去找,再到父类里面去找,不会去全局里面去找。

# 当对象在访问一个属性的时候,会先从自己的名称空间里面去找,然后去类里面去找,再到父类里面去找,不会去全局里面去找。
stu1.x = 'from stu1'
Student.x = 'from School class'
print(stu1.x)

###
from stu1

8,面向对象可拓展性总结

  通过面向对象,可以把数据与处理数据的功能捆绑在一起

  那么为何面向对象可拓展性高?

class Chinese:
    country = 'China'  # 可以随时加上变量(特征),而不需要改动其他地方
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex
    def eat(self):  # 也可以直接添加一个函数(技能)
        print('%s is eating'% self.name )
p1 = Chinese('egon', 18, 'male')
p2 = Chinese('alex', 38, 'female')
p3 = Chinese('wpq', 48, 'female')

print(p1.country)
print(p1.eat())

  随时加上特征和技能,而不需要改动其他的地方

9,对象互访问与交互

 1,想要对象能公共访问,须定义类属性,如果仅仅定义自身self属性,那么每个对象访问都是独立访问的

    
# 便携一个学生类,产生一堆的学生对象,并且要求有一个计数器(属性),统计总共示例了多少个对象

# 解答
class Student:
    count = 0  # 需要所有对象都能访问的参数,所以设置在类属性当中
    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age
        Student.count += 1

    def eat(self):
        print('%s is eating breakfast' % self.name)
stu1 = Student('王一丫', '', '18')
stu2 = Student('王二丫', '', '18')
stu3 = Student('王三丫', '', '18')

print(Student.count)

###
4

#注意点
class Student:
    count = 0  # 需要所有对象都能访问的参数,所以设置在类属性当中
    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age
#       self.count += 1  # 这里没有定义__init__ count对象,传类中的参数给count,这里定义的count参数是传给每个对象独有的,也就是说,这么定义,每个对象不能公共访问,就会造成计数一直都是1
# 应该定义一个类属性
        Student.count += 1

    def eat(self):
        print('%s is eating breakfast' % self.name)
stu1 = Student('王一丫', '', '18')
stu2 = Student('王二丫', '', '18')
stu3 = Student('王三丫', '', '18')

print(stu1.count)  # 每一个对象访问count都是相互独立的,故都是1
print(stu2.count)
print(stu3.count)

print(stu1.__dict__)  # 每个对象里面的count都相互独立
print(stu2.__dict__)
print(stu3.__dict__)

print(Student.count)

# 所以记录对象不能通过大家自己独有的方式去记录,要通过大家共有的方式去记录
# 在__init__下面定义一个类属性,Student.count += 1

###
在__init__中定义self.count += 1,结果一直都是1
在__init__中定义Student.count += 1,结果就可以随着对象的改变而改变了,结果为3
实例1

 2,如何实现不同类对象之间的交互

    
# 如何让对象之间交互完成事情

"""
实例二
模仿LOL定义两个英雄类
要求:
英雄需要又昵称,攻击力,生命值等属性
实例化出两个英雄对象
英雄之间可以互殴,被殴打的一方掉血,血量小于0则判定死亡
"""
class Gailen:
    city = 'Demacia'

    def __init__(self, nickname, life_value, aggressivity):
        self.nickname = nickname
        self.life_value = life_value
        self.aggressivity = aggressivity

    def attack(self, enemy):
        enemy.life_value -= self.aggressivity


class Riven:
    city = 'Noxus'

    def __init__(self, nickname, life_value, aggressivity):
        self.nickname = nickname
        self.life_value = life_value
        self.aggressivity = aggressivity

    def attack(self, enemy):
        enemy.life_value -= self.aggressivity

gailen = Gailen('暗影之拳', 120, 30)
riven = Riven('锐雯雯', 100, 40)

print(riven.life_value)
gailen.attack(riven)
print(riven.life_value)
实例2

10,面向对象进阶

原文地址:https://www.cnblogs.com/wuqiuming/p/9404804.html