Python面向对象设计和面向对象编程解析

简介: 我们都知道Python是一门灵活度很高的语言,它可以面向过程,面向对象,那我们今天说说Python中的面向对象设计和面向对象编程的区别面向对象设计和面向对象编程都提到了“面向对象”, 那么首先我们要搞清楚什么是对象对象:我们可以简单的理解为我们见到的每个实际存在的事物就是一个对象,如果一个人,一座房子,一只小猫等。

我们都知道Python是一门灵活度很高的语言,它可以面向过程,面向对象,那我们今天说说Python中的面向对象设计和面向对象编程的区别

面向对象设计和面向对象编程都提到了“面向对象”, 那么首先我们要搞清楚什么是对象

对象:我们可以简单的理解为我们见到的每个实际存在的事物就是一个对象,如果一个人,一座房子,一只小猫等。

那么我们想想,我们怎么面向对象,那就是以对象为中心,去描述这个对象,这个对象有什么特点,什么属性,什么功能等,想想假如你要去向别人描述一个丢失的小猫(一个对象),你要怎么描述呢?小够的品种,大小,毛色,等等。 当你把着一些特征或者属性描述清楚之后,一个对象就被定义下来了。

知道对象的概念之后,我们进入主题

1.面向对象设计

说到设计,我们可以理解为是一种想法,思路,就是把对象的属性,功能(python里用函数表达)糅合在一起形成一个对象,这种思想可以简单的理解为面向对象设计,不是说必须用CLASS这种,才叫面向对象设计,下面我们举个例子

def cat(name,gender,type):
    # 猫的的动作或者叫功能
    def cry(cat):
        print('一条小猫[%s],喵喵' % cat['name'])
    def run(cat):
        print('一条[%s]小猫正在跑' % cat['type'])
    def init(name,gender,type):
        cat = {
            'name':name,
            'gender': gender,
            'type': type,
            'cry':cry,
            'run':run,
        }
        return cat
    return init(name,gender,type)

cat=cat('毛球','公','波斯猫')
print(cat)
cat['cry'](cat)

结果

{'name': '毛球', 'gender': '公', 'type': '波斯猫', 'cry': <function cat.<locals>.cry at 0x0000022C6C9B71E0>, 'run': <function cat.<locals>.run at 0x0000022C6C9B7158>}
一条小猫[毛球],喵喵

上面我们用纯函数的方式去描述了一只小猫,但是我们也可以把上面这张方式理解为面向对象设计,因为上面我们把猫的属性和功能函数结合在一起,形式了一个对象。

我们用

cat=cat('毛球','公','波斯猫')

来生成一个对象,我们可以调用对象的属性和函数等等,这些都是我们熟悉的面向对象设计,但是我们不能说这种方式叫面向对象编程。

2.面向对象编程,

这个在很多语言中都在大量使用,简单的说使用Class来描述对象的方式就是面向对象编程。Python中当然也可以使用面向对象编程,但是不强求,如JAVA之类的编程语言就强制要求使用面向对象编程,个人认为不太友好。下面我们把上面的例子改成面向对象编程的方式来看看

class Cat:
    def __init__(self,name,gender,type):
        self.name = name
        self.gender = gender
        self.type = type

    def cry(self):
        print('一条小猫[%s],喵喵' % self.name)
    def run(self):
        print('一条[%s]小猫正在跑' % self.type)

cat =  Cat('毛球','公','波斯猫')
print(Cat)
cat.cry()

上面我们改成了个class的方式来编程,可以说就是使用面向对象编程的方式。也是我们熟悉的类方式。

3.面向对象编程的基础知识点拨

3.1类和函数的属性分类

类属性包含:数据属性和函数属性

对象属性包括:数据属性,对象如果向调用函数属性,其实是调用的类的函数属性

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

类的函数属性是绑定给对象用的

怎么理解呢?我们可以使用__dict__方法来看属性

class Cat:
    weight = 5; #新定义了一个类的数据属性
    def __init__(self,name,gender,type): #实例属性
        self.name = name
        self.gender = gender
        self.type = type

    def cry(self): #类的函数属性
        print('一条小猫[%s],喵喵' % self.name)
    def run(self):  #类的函数属性
        print('一条[%s]小猫正在跑' % self.type)

cat =  Cat('毛球','公','波斯猫')
print(Cat.__dict__)
print(cat.__dict__)

结果

{'__module__': '__main__', 'weight': 5, '__init__': <function Cat.__init__ at 0x0000021E5DC671E0>, 'cry': <function Cat.cry at 0x0000021E5DC67158>, 'run': <function Cat.run at 0x0000021E5DC67268>, '__dict__': <attribute '__dict__' of 'Cat' objects>, '__weakref__': <attribute '__weakref__' of 'Cat' objects>, '__doc__': None}


{'name': '毛球', 'gender': '公', 'type': '波斯猫'}

上面一行是类的属性,我们可以看到我们定义的weight,'cry','run'等类的数据和函数属性

下面一行是对象的属性,只有init里面定义的数据属性,没有函数属性

当函数想调用方法时,是先从自己的属性里面找,如果没有就去上层类的__dict__里面去寻找,执行,所以我们说对象执行方法其实执行的是类的函数属性。

我们看到上面__dict__里面还有一些其他自带属性解释如下

#python为类内置的特殊属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)

3.2 self到底什么意思,什么时候使用

self我们可以理解为实例对象自己,那为什么在面向对象编程的时候,类的每个函数都要在第一个参数放self呢? 我的理解一方面是面向对象编程的语法需要,二深层次的说是把类的数据属性和函数属性糅合在一起,满足面向对象设计的思想

self在对象实例化的时候,会自动传入,如果函数属性里面不定义self会报错

class Cat:
    weight = 5;
    def __init__(self,name,gender,type):
        self.name = name
        self.gender = gender
        self.type = type

    def cry(): #没有写self
        print('一条小猫喵喵')
    def run(self):
        print('一条[%s]小猫正在跑' % self.type)

cat =  Cat('毛球','公','波斯猫')
cat.cry() #对象调用类的函数属性时候,会自己传入self也就是实例自己,作为第一个参数

结果报错

Traceback (most recent call last):
File "C:/Users/aryin/Desktop/mysite2/面向对象.py", line 14, in

cat.cry()

TypeError: cry() takes 0 positional arguments but 1 was given

仔细看报错,cry() takes 0 positional arguments but 1 was given,说我们给它传了一个参数,但是上面的代码里,我们什么也没传,所以这是python自己给我们默认传了一个self参数

那我们看看我们直接用类自己来调用它的函数属性,看看会不会自己传入self参数

class Cat:
    weight = 5;
    def __init__(self,name,gender,type):
        self.name = name
        self.gender = gender
        self.type = type

    def cry(self): #没有写self
        print('一条小猫喵喵')
    def run(self):
        print('一条[%s]小猫正在跑' % self.type)

cat =  Cat('毛球','公','波斯猫')
Cat.cry() #类调用自己的函数属性,不传入参数

结果报错

Traceback (most recent call last):
File "C:/Users/aryin/Desktop/mysite2/面向对象.py", line 15, in

Cat.cry()

TypeError: cry() missing 1 required positional argument: 'self'

看错误是少了一个参数,说明当类自己调用函数属性的时候,不会自己传入self,cry函数需要一个参数self,所以报错了,所以正确的使用是

class Cat:
    weight = 5;
    def __init__(self,name,gender,type):
        self.name = name
        self.gender = gender
        self.type = type

    def cry(self): #没有写self
        print('一条小猫喵喵')
    def run(self):
        print('一条[%s]小猫正在跑' % self.type)

cat =  Cat('毛球','公','波斯猫')
Cat.cry(cat) #类调用自己的函数属性,不传入参数

所以只有当对象去调用类的函数属性或者说方法的时候才会自动传入self属性,类自己调用时候不会,要自己传入实例。

当然我们一般不这么使用类来调用自己的函数属性,我们可以使用类方法来实现调用

class Cat:
    weight = 5;
    def __init__(self,name,gender,type):
        self.name = name
        self.gender = gender
        self.type = type

    @classmethod
    def cry(cls): #没有写self        print('一条小猫喵喵')
    def run(self):
        print('一条[%s]小猫正在跑' % self.type)

Cat.cry()

结果:

一条小猫喵喵

这里看到改动的地方,是传入的cls, 就是类自己,classmethod类静态方法实现类调用自己的函数属性时候不需要显示传入cls参数,而是自动传入,classmethod类静态方法实际就是绑定了类和自己的函数属性。

3.3 实例化到底做了什么(__init__方法)

当对象实例化的时候,会先去执行__init__函数,对象会去__init__里面找到自己的数据属性

class Cat:
    weight = 5;
    def __init__(self,name,gender,type):
        print('开始初始化')
        self.name = name
        self.gender = gender
        self.type = type
        print('结束初始化')


    def cry(self): #没有写self
        print('一条小猫喵喵')
    def run(self):
        print('一条[%s]小猫正在跑' % self.type)

cat=Cat('毛球','公','波斯猫') #实例化
print(cat.__dict__)

结果:

开始初始化
结束初始化
{'name': '毛球', 'gender': '公', 'type': '波斯猫'}

看到__init__函数里面已经执行了,对象的数据属性也得到了。

今天说到这里,个人意见,望指教。

更多源代码文章请关注:pythonislover

目录
相关文章
|
18天前
|
存储 缓存 算法
Python中collections模块的deque双端队列:深入解析与应用
在Python的`collections`模块中,`deque`(双端队列)是一个线程安全、快速添加和删除元素的双端队列数据类型。它支持从队列的两端添加和弹出元素,提供了比列表更高的效率,特别是在处理大型数据集时。本文将详细解析`deque`的原理、使用方法以及它在各种场景中的应用。
|
1天前
|
调度 Python
Python多线程、多进程与协程面试题解析
【4月更文挑战第14天】Python并发编程涉及多线程、多进程和协程。面试中,对这些概念的理解和应用是评估候选人的重要标准。本文介绍了它们的基础知识、常见问题和应对策略。多线程在同一进程中并发执行,多进程通过进程间通信实现并发,协程则使用`asyncio`进行轻量级线程控制。面试常遇到的问题包括并发并行混淆、GIL影响多线程性能、进程间通信不当和协程异步IO理解不清。要掌握并发模型,需明确其适用场景,理解GIL、进程间通信和协程调度机制。
12 0
|
1天前
|
API Python
Python模块化编程:面试题深度解析
【4月更文挑战第14天】了解Python模块化编程对于构建大型项目至关重要,它涉及代码组织、复用和维护。本文深入探讨了模块、包、导入机制、命名空间和作用域等基础概念,并列举了面试中常见的模块导入混乱、不适当星号导入等问题,强调了避免循环依赖、合理使用`__init__.py`以及理解模块作用域的重要性。掌握这些知识将有助于在面试中自信应对模块化编程的相关挑战。
12 0
|
5天前
|
SQL API 数据库
Python中的SQLAlchemy框架:深度解析与实战应用
【4月更文挑战第13天】在Python的众多ORM(对象关系映射)框架中,SQLAlchemy以其功能强大、灵活性和易扩展性脱颖而出,成为许多开发者首选的数据库操作工具。本文将深入探讨SQLAlchemy的核心概念、功能特点以及实战应用,帮助读者更好地理解和使用这一框架。
|
11天前
|
Python
Python面向对象编程学习应用案例详解
面向对象编程在Python中通过类定义对象结构和行为。示例:1) 使用`class`关键字定义类,如`class Person`;2) `__init__`方法初始化对象属性,如`self.name`和`self.age`;3) 实例化对象,如`person1 = Person(&quot;张三&quot;, 25)`;4) 访问属性和方法,如`person1.name`;5) 定义类方法,如`def introduce(self)`;6) 调用方法,如`person1.introduce()`;7) 类继承,如`class Student(Person)`;8) 多态,通过继承重写方法实现。
9 1
|
18天前
|
数据采集 数据挖掘 Python
Python中collections模块的Counter计数器:深入解析与应用
在Python的`collections`模块中,`Counter`是一个强大且实用的工具,它主要用于计数可哈希对象。无论是统计单词出现的频率,还是分析数据集中元素的分布情况,`Counter`都能提供快速且直观的结果。本文将深入解析`Counter`计数器的原理、用法以及它在实际应用中的价值。
|
24天前
|
Python
Python面向对象编程简介
Python面向对象编程简介
17 1
|
24天前
|
安全 Python
Python封装:深入解析与应用
封装是Python面向对象编程的关键,通过隐藏对象属性和实现细节,提供公共访问方式,确保代码安全和可维护。实现封装主要通过类和对象,使用私有属性(__前缀)及访问器/修改器方法。封装能隐藏内部状态、统一接口、复用代码和增强扩展性。示例展示了如何用私有属性和访问器方法控制属性访问。掌握封装有助于编写高效、灵活的代码。
|
5月前
|
Python
一文学会Python面向对象中封装、继承、多态使用
一文学会Python面向对象中封装、继承、多态使用
80 0
|
5月前
|
Python
浅谈Python面向对象中的继承与mro
浅谈Python面向对象中的继承与mro
25 0

推荐镜像

更多