面向对象:编程范式、类、对象

编程范式:

1. 面向过程编程: 核心是“过程”,“过程”指的是解决问题的步骤;就相当于在设计一条流水线

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

  缺点:可扩展性差,前一发动全身

2. 面向对象:核心是“对象”,对象就是特征与技能的结合体

 优点: 可扩展性强

缺点: 编程复杂度高

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

类:

类就是一系列对象相似的特征与技能的结合体(相当于一个模板),特征用变量表示,技能用函数表示

强调: 站在不同的角度,得到的分类是不一样的

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

定义类、产生对象的方法如下:

"""定义类"""
class Student:  #  类的首字母大写
    school = "Luffycity"  

    def learn(self):
        print("is learning")

    def eat(self):
        print("is eating")

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

"""调用类产生对象"""
stu1 = Student()   #  Student() 不是执行类体的代码,而是得到一个返回值,这个返回值就是产生的对象;这个过程也叫“实例化”
stu2 = Student()   #  类名调用一次就是实例化一次
stu3 = Student()

print(stu1)
print(stu2)
print(stu3)

#  输出结果:
#  <__main__.Student object at 0x0000001F205C6438>
#  <__main__.Student object at 0x0000001F205C66D8>
#  <__main__.Student object at 0x0000001F205C6668>

类的使用:

定义类时,在类定义阶段它内部的代码就能够运行,如下:

class Student:  #  类的首字母大写
    school = "Luffycity"  # 特征
    print("test")

    def learn(self):   # 技能
        print("is learning")

    def eat(self):
        print("is eating")

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

#  运行结果:
#  test 

查看类里面的名称空间:

class Student:  #  类的首字母大写
    school = "Luffycity"  # 类的数据属性

    def learn(self):   # 类的函数属性
        print("is learning")

    def eat(self):
        print("is eating")

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

print(Student.__dict__)
print(Student.__dict__["school"])
print(Student.__dict__["learn"])

"""查看"""
print(Student.school)
print(Student.learn)

"""类定义完后增加属性"""
Student.country = "China"  #  往Student这个类里面增加了 country = "China"
print(Student.__dict__)
print(Student.country)

"""删除"""
del Student.country
print(Student.__dict__)

"""修改"""
Student.country = "Greater China"
print(Student.country)

#  打印结果:
#  {‘__module__‘: ‘__main__‘, ‘school‘: ‘Luffycity‘, ‘learn‘: <function Student.learn at 0x000000711C26B9D8>, ‘eat‘: <function Student.eat at 0x000000711C26BA60>, ‘sleep‘: <function Student.sleep at 0x000000711C26BD90>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘Student‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Student‘ objects>, ‘__doc__‘: None}
#  Luffycity
#  <function Student.learn at 0x000000711C26B9D8>
#  Luffycity
#  <function Student.learn at 0x000000711C26B9D8>
#  {‘__module__‘: ‘__main__‘, ‘school‘: ‘Luffycity‘, ‘learn‘: <function Student.learn at 0x000000711C26B9D8>, ‘eat‘: <function Student.eat at 0x000000711C26BA60>, ‘sleep‘: <function Student.sleep at 0x000000711C26BD90>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘Student‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Student‘ objects>, ‘__doc__‘: None, ‘country‘: ‘China‘}
#  China
#  {‘__module__‘: ‘__main__‘, ‘school‘: ‘Luffycity‘, ‘learn‘: <function Student.learn at 0x000000711C26B9D8>, ‘eat‘: <function Student.eat at 0x000000711C26BA60>, ‘sleep‘: <function Student.sleep at 0x000000711C26BD90>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘Student‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Student‘ objects>, ‘__doc__‘: None}
#  Greater China

类内部定义的变量是类的数据属性 ,定义的函数是其函数属性

类的用途:

  1. 对属性的操作

  2. 实例化产生一个个对象 (利用  Student() 方法)

对象的使用方法:

利用 init 方法来为对象定制自己独有的特征

class Student:
    school = "Luffycity"

    def __init__(self,name,gender,age):  #  实例化的时候就会自动调用 __init__函数
        self.Name = name
        self.Gender = gender
        self.Age = age   # 字典形式

        """
        stu1.Name = "苍老师"
        stu1.Gender = "女"
        stu1.Age = 18
        """
    def learn(self):
        print("is learning")
    def eat(self):
        print("is eating")
    def sleep(self):
        print("is sleeping")

stu1 = Student("苍老师","女",18)stu2 = Student("武藤兰","男",38)

"""
有__init__函数时的实例化步骤:
1. 先产生一个空对象stu1(不带自己独特属性的对象)
2. 触发__init__函数,触发方式为:Student.__init__() , 这是一个函数,就需要按照函数的方式进行传参,即: Student.__init__(stu1,name,gender,age) (第一步生成的对象stu1传入self的位置)
   Student.__init__(stu1,name,gender,age) 产生的效果如__init__函数中的注释所示。
"""

"""
stu1 = Student("苍老师","女",18)  这是在给一个对象定制一个属性,与类添加属性一个道理,往对象里面添加属性也涉及到名称空间的变动,只不过这个名称空间是stu1的名称空间(因为是往stu1这个对象里面添加的新属性)
"""
print(stu1.__dict__)
# 打印结果:
# {‘Name‘: ‘苍老师‘, ‘Gender‘: ‘女‘, ‘Age‘: 18}

""" 通过__init__的方法, stu1这个对象不但拥有类共有的那些特征和技能,并且也有了自己独有的属性"""

"""查看"""
print(stu1.Name)
print(stu1.Gender)
# 打印结果:
# 苍老师
# 女

"""改"""
stu1.Name = "苍井空"
print(stu1.__dict__)
print(stu1.Name)
# 打印结果:
# {‘Name‘: ‘苍井空‘, ‘Gender‘: ‘女‘, ‘Age‘: 18}
# 苍井空

"""增加"""
stu1.job = "adult video"
print(stu1.__dict__)
print(stu1.job)
# 打印结果:
# {‘Name‘: ‘苍井空‘, ‘Gender‘: ‘女‘, ‘Age‘: 18, ‘job‘: ‘adult video‘}
# adult video

"""删除"""
del stu1.job
print(stu1.__dict__)
# 打印结果:
# {‘Name‘: ‘苍井空‘, ‘Gender‘: ‘女‘, ‘Age‘: 18}

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

类中的函数属性:是绑定给对象使用的,而且绑定到不同的对象是不同的绑定方法

还以上面的代码为例:

print(Student.school,id(Student.school))
print(stu1.school,id(stu1.school))

# 打印结果:
# Luffycity 586247585648
# Luffycity 586247585648

"""类中的数据属性是所有对象共有的,用的都是同一块内存地址"""

"""类中的函数属性:是绑定给对象,而且绑定到不同的对象是不同的绑定方法"""
print(Student.learn)print(stu1.learn)print(stu2.learn)

# 打印结果:  (函数的内存地址也不一样)# <function Student.learn at 0x0000005FB155BA60># <bound method Student.learn of <__main__.Student object at 0x0000005FB15667B8>>   # bound method 绑定方法不一样# <bound method Student.learn of <__main__.Student object at 0x0000005FB15667F0>>
 

把上述例子中类的代码稍微修改,如下:

class Student:
    school = "Luffycity"

    def __init__(self, name, gender, age):  # 实例化的时候就会自动调用 __init__函数
        self.Name = name
        self.Gender = gender
        self.Age = age  # 字典形式

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

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

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

stu1 = Student("苍老师", "女", 18)
stu2 = Student("武藤兰","男",38)

调用 Student.learn() 函数的方法:(此函数需传入参数)

Student.learn(stu1)   # Student.learn()就是一个普通的函数,所以可以利用函数的调用方式去执行它;函数的参数要传入上一步产生的stu1, 因为在类中定义learn()函数时,里面有参数self

# 执行结果:
# 苍老师 is learning

调用stu1.learn()函数的方法: (此函数无需传入参数,因为learn功能只需传入参数self,而stu1会自动传入self)

"""调用stu1.learn()函数"""
stu1.learn()   # 这个函数调用的是类Student下的learn的功能,stu1会作为参数自动传入到self这个形参中

# 执行结果:
# 苍老师 is learning

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

类中定义的功能(即 函数)是给对象使用的(绑定给对象使用的),而且是哪个对象来调用就把哪个对象作为参数自动传入到self中(这是 绑定关系),这样 哪个对象在调用就是哪个对象在执行类中的功能;类如果自己使用还需要自己传入对象(传入到self中),会比较笨拙

对象只存放自己独有的特征,相似的特征都放在类里面;这涉及到对象的属性查找问题,如果对象中的属性跟类中的属性重名,则以对象中的属性为准(类似于函数中变量的先局部后全局)(例外,属性不会去全局里面找,因为你是在调用类,或者说这是类的调用)

"""有重名"""
stu1.x = "CN"
Student.x = "中国"

print(stu1.x)
print(Student.x)

# 打印结果:
# CN
# 中国

"""无重名时,对象调用类中的"""
Student.x = "中国"

print(stu1.x)
print(Student.x)

# 打印结果:
# 中国
# 中国

补充说明1:

  1. 站在不同角度,定义出的类是不同的

  2. 现实中的类并不完全等同于程序中的类,比如现实中的公司类,在程序中有时需拆分成部门类、业务类等

  3. 有时为了变成需求,程序中可能会定义现实中不存在的类,比如策略类,现实中不存在,但在程序中是一个很常见的类

补充说明2:

  Python中一切皆对象,并且在Python3中统一了类与类型的概念

class Student:
    school = "Luffycity"

    def __init__(self, name, gender, age):  # 实例化的时候就会自动调用 __init__函数
        self.Name = name
        self.Gender = gender
        self.Age = age  # 字典形式

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

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

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

print(type([1,2]))
print(list)    # [1,2] 和 list是Python中的列表这个数据类型
print(Student)   # Student 是我们自己创建的类

# 打印结果:
# <class ‘list‘>
# <class ‘list‘>
# <class ‘__main__.Student‘>

""" Python3中统一了类与类型的概念 """

# 站在类的角度考虑下面已学过的知识
list1 = [1,2,3]   #  这种方法的本质是 list1 = list([1,2,3])  即 调用list这个类并传入参数[1,2,3],进而产生list1这个对象,并且[1,2,3]放入到了list1的命名空间中; list1中独有的特征就是[1,2,3]
list2 = []   # 同理, list2 = list()

list1.append(4)  # 这行代码的含义是:list1这个对象调用了list这个类下面的 append() 这个功能(函数)。
print(list1)
"""
list1.append(4) 其实就相当于 list.append(list1,4)
即 list这个类调用其内部的append()函数,并把list1这个对象传入到self这个形参中
"""
list.append(list1,5)
print(list1)

# 打印结果:
# [1, 2, 3, 4]
# [1, 2, 3, 4, 5]

list2.append(1)  # list2.append(1) : 添加的1只能添加到list2中,不会添加到list1中,因为是list2这个对象在调用append(1)这个功能
print(list2)

#  打印结果:
#  [1]

"""所以,在Python中一切皆对象"""

可扩展性:

  使用类可以将数据与专门操作该数据的功能捆绑在一起

例题1:

  编写一个学生类,产生多个学生对象

  要求: 有一个计数器(属性),统计总共实例化了多少个对象

代码如下:

class Student:
    school = "luffycity"
    count = 0

    def __init__(self,name,gender,age):
        self.name = name
        self.gender = gender
        self.age = age

        # self.count += 1  # 这种方式是不可行的,因为每次添加count时都添加到了对象的特有属性里面,再产生下一个对象时,新产生的对象并不知道上一个对象count的值是多少;而且由于 __init__ 里面没有对 count 这个变量赋值,所以 self.count 会向类的公共属性里面去寻找count 的值

        """正确写法"""
        Student.count += 1   # 在 __init__函数里面对类Student的公共属性count进行处理;count变量并没有添加到对象命名空间中(没有添加到对象的独有属性中),count一直都是在类Student的命名空间里

    def learn(self):
        print("%s is learning" %self.name)

"""
分析要求: 每次实例化都会触发 __init__ 函数,所以可以考虑在 __init__ 上进行计数
首先在类的公共属性上添加一个 count = 0
"""
stu1 = Student("neo","male",18)
stu2 = Student("苍老师","female",16)
stu3 = Student("美奈子","female",17)

print(stu1.count)  # 此时的 stu1.count 调用的是类 Student中的变量count,stu1中是没有count这个变量的
print(stu2.count)
print(stu3.count)
print(stu1.__dict__)
print(stu2.__dict__)
print(stu3.__dict__)

print(Student.count)

# 打印结果:
# 3
# 3
# 3
# {‘name‘: ‘neo‘, ‘gender‘: ‘male‘, ‘age‘: 18}
# {‘name‘: ‘苍老师‘, ‘gender‘: ‘female‘, ‘age‘: 16}
# {‘name‘: ‘美奈子‘, ‘gender‘: ‘female‘, ‘age‘: 17}
# 3

例题二:

  模仿LOL定义两个英雄类  

  要求:

    英雄需要有昵称、攻击力、生命值等属性

    实例化出两个英雄对象

    英雄之间可以互殴,被打的一方掉血,血量小于0则判定为死亡

以下是自己写的:(只定义了一个英雄类)

class Hero:

    def __init__(self,name,attack,life):
        self.name = name
        self.attack = attack
        self.life = life

    def fighted(self,attacked = 0):
        self.life -= attacked
        if self.life <= 0:
            print("%s is dead" %self.name)
        else:
            print("%s is alive" %self.name)

kasaa = Hero("卡萨丁",1000,2000)
kayle = Hero("凯尔",1300,1500)

kayle.fighted(kasaa.attack)
kayle.fighted(kasaa.attack)

示例代码:

class Garen:
    camp = "Demacia"

    def __init__(self,nickname,attack,life):
        self.nickname = nickname
        self.attack = attack
        self.life = life

    def attacking(self,enemy):
        enemy.life -= self.attack

class Riven:
    camp = "Noxus"

    def __init__(self,nickname,attack,life):
        self.nickname = nickname
        self.attack = attack
        self.life = life

    def attacking(self,enemy):
        enemy.life -= self.attack

garen = Garen("草丛伦",30,100)
riven = Riven("瑞雯雯",50,80)

print(riven.life)
garen.attacking(riven)   # 英雄(对象)之间的交互
print(riven.life)

# 运行结果
# 80
# 50

上述代码中有大量重复的代码,利用“继承”来解决。(转下篇文章)

原文地址:https://www.cnblogs.com/neozheng/p/8479922.html

时间: 2024-10-12 13:39:32

面向对象:编程范式、类、对象的相关文章

Objective-C语言介绍 、 Objc与C语言 、 面向对象编程 、 类和对象 、 属性和方法 、 属性和实例变量

Objective-C语言介绍 . Objc与C语言 . 面向对象编程 . 类和对象 . 属性和方法 . 属性和实例变量 1 第一个OC控制台程序 1.1 问题 Xcode是苹果公司向开发人员提供的集成开发环境(非开源),用于开发Mac OS X,iOS的应用程序.其运行于苹果公司的Mac操作系统下. 本案例要求使用集成开发工具Xcode编写OC的HelloWorld程序,在Xcode的控制台中, 1.2 方案 首先,启动集成开发工具Xcode. 然后,创建OC语言的工程. 最后,运行所创建的工

java面向对象编程(1)-类与对象

1.问题的提出      张老太养了两只猫猫:一只名字叫小白,今年3岁,白色.还有一只叫小花,今年100岁,花色.请编写一个程序,当用户输入小猫的名字时,就显示该猫的名字,年龄,颜色.如果用户输入的小猫名错误,则显示张老太没有这只猫. //用前面学习过的知识写出代码如下: public class Demo107{ public static void main(String []args){ int a=49;//输入的名字49,50 int cat1age=3; //第一只猫 String

面向对象编程,类和对象

面向对象编程,类和对象 一.面向对象 1.什么是面向对象 ? 面向对象是一种编程思想,是前辈们总结出的经验,指导程序员如何编写出更好的程序 , 核心是对象,程序就是一系列对象的集合, 程序员负责调度控制这些对象来交互着完成任务. 2.几个案例 案例1:把大象装进冰箱 ? ? 面向过程: ? 1.打开冰箱 ? 2.装入大象 ? 3.关闭冰箱 ? 面向对象: ? 找个具备装大象的技能的对象 总结:在面向对象中程序员的角度发生改变,从具体的操作者变成了指挥者 强调:对象不是凭空产生的,需要我们自己设计

C++ Primer 学习笔记_72_面向对象编程 --句柄类与继承[续]

面向对象编程 --句柄类与继承[续] 三.句柄的使用 使用Sales_item对象能够更easy地编写书店应用程序.代码将不必管理Item_base对象的指针,但仍然能够获得通过Sales_item对象进行的调用的虚行为. 1.比較两个Sales_item对象 在编写函数计算销售总数之前,须要定义比較Sales_item对象的方法.要用Sales_item作为关联容器的keyword,必须能够比較它们.关联容器默认使用keyword类型的小于操作符,可是假设给Sales_item定义小于操作符,

C++ Primer 学习笔记_71_面向对象编程 --句柄类与继承

面向对象编程 --句柄类与继承 引言: C++中面向对象编程的一个颇具讽刺意味的地方是:不能使用对象支持面向对象编程,相反,必须使用指针或引用. void get_prices(Item_base object, Item_base *pointer, Item_base &reference){ //需要根据指针或引用实际所绑定的类型进行调用 cout<< pointer ->net_price(1)<< endl; cout<< reference.n

Python源码 -- C语言实现面向对象编程(基类&amp;派生类&amp;多态)

由于公司的ERP系统数据量大,有40G+的数据,并发用户90+,连接数1000+,原来的IO性能跟不上用户的操作响应需求,报表查询慢,该做的索引都做过了,索引每周重建一次,还是解决不了问题,为此,公司新购了dell poweredge R720xd服务器,该套服务器支持2个阵列,24个硬盘,双CPU,64G内存,比较牛X的了,我们创建两个raid,两块SAS硬盘做Raid1,6块SSD硬盘做Raid10,系统装好了,高兴呀,但结过测试发现,总有一个raid速度相当慢,和台式机速度一样,我地妈呀,

object-c编程tips-给类对象添加属性

此问题来源于网络封装的一个内容,由于保密的问题,我只叙述我业余的一些想法. 基本思想: 网络请求大家应该都会用一个基类的BaseNetWork, 然后由派生类继承于BaseNetWork,并实现一些特殊的方法. 一般标准的流程是传入block, 当网络请求完毕后,通过block回调回来.这里叙述的关键不是如何实现一个网络请求和回调block的相关内容,而是如何取消请求. 一般基类会实现一个cancelNetWork方法,它根据自己的url进行cancel操作. 举例: 我们使用 DerivedN

Python面向对象编程、类

一.面向对象编程 面向对象--Object Oriented Programming,简称oop,是一种程序设计思想.在说面向对象之前,先说一下什么是编程范式,编程范式你按照什么方式来去编程,去实现一个功能.举个例子,你要做饭,可以用电磁炉,也可以用煤气灶.不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路,两种最重要的编程范式分别是面向过程编程和面向对象编程. 提到面向对象,就不得不提到另一种编程思想,面向过程:什么是面向过程呢,面向过程的思想是把一个项目.一件事情按照一定的顺

python学习笔记(七):面向对象编程、类

一.面向对象编程 面向对象--Object Oriented Programming,简称oop,是一种程序设计思想.在说面向对象之前,先说一下什么是编程范式,编程范式你按照什么方式来去编程,去实现一个功能.举个例子,你要做饭,可以用电磁炉,也可以用煤气灶.不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路,两种最重要的编程范式分别是面向过程编程和面向对象编程. 提到面向对象,就不得不提到另一种编程思想,面向过程:什么是面向过程呢,面向过程的思想是把一个项目.一件事情按照一定的顺

PHP面向对象编程学习之对象基础

php虽然是一门学习起来非常简单的语言,但是这门语言也包含了对面向对象编程的支持.尤其是随着php5的发布,php对面向对象的支持有了很大的进步.最近学习了一下php的面向对象编程,不禁感慨,面向对象真的是一种非常优雅的编程,最主要的是真的很难! 学习面向对象,当然首先就要了解什么是类,什么是对象,类和对象有什么关系?类和对象的定义就不在这里赘述了,相信大家对类和对象都有一个基本的认识.还是主要说一下类和对象的关系:类是用于生成对象的模板,而对象是类的实例.如何定义类和实例化对象就不多说了,这都