什么是面向对象的编程?
-
编程范式,该范式围绕对象组织代码:
我们代表现实世界中的实体,例如代码行中的汽车,建筑物,动物和其他各种选项,以便它们按对象定义进行分类。使用概念来改善组织和维护。 -
是具有状态(data)的实体:就像具有在对象方向内特征的真实世界对象一样,我们可以使用属性表示。
-
它也具有行为(方法):在对象取向中,它不会忽略现实世界中实体(对象)的功能。我们可以通过代表对象行为的函数的定义表示。
OOP的优点和缺点是什么?
好处:
代码重复使用
将无需为具有相同属性的不同对象创建每个类。像汽车类一样,我不需要为每个汽车模型创建一个类(代码行)。例如,让我们认为有一家称为“ OO汽车”的工厂,该工厂生产两种类型的汽车“ OO Turbo”和“ OO 4x4”。您同意我的看法,这些汽车有一个工厂,4个轮子,1个引擎,颜色.....和其他几个部分。我们不会介绍所有细节。但是,想象一下您是程序员,为每辆车定义一堂课,并且大多数时候他们都会有相同的细节。在这种情况下,公司“ OO汽车”开发了一辆新车。同样,您将必须创建一个与以前的汽车相同特征的类。因此,您将不必做出巨大的重复性。这是对象方向的来源。我们仅定义一个类,以便我们可以重用不同的汽车。
错误
class Car_OO_Turbo():
def __init__(self, model, engine, color):
self.model = model
self.engine = engine
self.color = color
class Car_OO_4x4():
def __init__(self, model, engine, color):
self.model = model
self.engine = engine
self.color = color
正确
class Car():
def __init__(self, model, engine, color):
self.model = model
self.engine = engine
self.color = color
易于维护
对象方向使在代码中进行更改变得容易,从而在与外部代码隔离的类中进行维护,从而避免问题。除了将重点放在发生的问题上。
缺点:
复杂性
,但并非一切都是一个优势,随着代码的发展,我们可以遇到庞大的类声明,对属性和方法越来越复杂。班级之间的关系,因此可能影响维护的几个相关类。
调试难度
具有继承,多态性,关联和其他模式的越来越多的类。他们彼此之间更加相关。这使得很难寻找代码提出的问题和错误。花更多时间调试代码。
概念
目的
该对象被定义为实体,因此我们可以代表现实世界中的某些东西。例如:
- 汽车
- 地址
- 主页
- 食物
- 飞机
仅由于标签是汽车或房屋而没有定义该物体。对象具有特征(属性)和过程(方法)。因此,当我们打算在OOP中代表对象时,我们添加了这些规格,以便其在要开发的系统中具有全面的表示。
班级
类是一个模板,或者是我们想要在项目中设计一个现实世界对象的模板。在类中,我们避免创建几个对象,使用类来表示不同的对象,它们的特征是不同的,在以下步骤中,这种形式的表示形式将变得更加清晰。
示例
- 汽车类
- 客户类
- 书类
只有一个类,我们可以定义其属性和方法。
使用Python语言,我们可以创建一个类似于下面的示例的类。
class Car:
...
class Client:
...
class Book:
...
属性
属性是对象的特征,以餐厅为例,有序对象可以表示为类。定义后,我们将请求的特征(属性)添加到类中。就像客户的名字,选择的零食,肉类等。您可以在大型快餐中观察到订单对象的示例,当您选择,付款和等待以获取收据时,在这种情况下,这是您的收据您的名字和另一份副本去了厨房,以准备您请求的特征。在某些人中,您甚至不再需要收据纸。您的订单内有一台显示器,外面有一个,外面有准备订单的订单。
-
“ __ init __()” :此方法在Python语言类中具有构造函数定义,在此方法中,我们将定义类属性。
-
“ self” :此参数的定义是由我们将在下一步中看到的类的内部方法使用。在我们不需要将类的参数传递给类的每种方法的地方。一旦实例化, self 就会在内部函数内定义。可以使用属性的使用。
class Order:
def __init__(
self,
customer_name: str,
snack: str,
meat_stitch: str,
soda: bool,
potato: bool,
):
self.customer_name = customer_name
self.snack = snack
self.meat_point = meat_stitch
self.soda = soda
self.potato = potato
order1 = Order('Severius', 'X-Bacon','To the point', False, False)
print(
f'Customer name: {order1.customer_name}\n'
f'Snack Chosen: {order1.snack}\n'
f'Meat point: {order1.meat_point}\n'
f'Ordered soda: {order1.soda}\n'
f'Ordered Potato: {order1.potato}\n'
)
# OUTPUT:
# Customer name: Severius
# Snack Chosen: X-Bacon
# Meat point: To the point
# Ordered soda: False
# Ordered Potato: False
order2 = Order('Kratos', 'X-Fish','To the point', True, True)
print(
f'Customer name: {order2.customer_name}\n'
f'Snack Chosen: {order2.snack}\n'
f'Meat point: {order2.meat_point}\n'
f'Ordered soda: {order2.soda}\n'
f'Ordered Potato: {order2.potato}\n'
)
# output:
# Customer name: Kratos
# Snack Chosen: X-Fish
# Meat point: To the point
# Ordered soda: True
# Ordered Potato: True
方法
方法是我们在类中代表对象的函数。以汽车为例,我们可以定义功能,例如打开引擎,关闭引擎,打开大灯,关闭大灯,激活警报,停用警报,移动,停止,打开门... .....和数千个汽车可以具有的其他功能。如果您熟悉Python。我们通过编写类的内部函数来定义类中的方法,该函数仅保留在其范围内。除非我们实例化对象,否则班级以外什么都不会访问。
class Car:
def __init__(self, model):
self.model = model
def turn_on_car(self):
return 'Car On'
def turn_off_car(self):
return 'Car off'
car.turn_on_car()
#output: 'Car On'
car.turn_off_car()
#output: 'Car off'
属性可见性
属性可见性为共享类功能提供了Python语言中的选项。这可能在外部或内部发生。并非总是需要开发软件时,我们需要使用外部属性或方法,因此代码的其他部分不能外部访问该类,而只能内部保护属性和方法。用Python语言,有3个公开,受保护,私人。但是他们有与其他编程语言有所不同的语言特点。
公共
Python语言具有的访问修饰符之一。它是 public ,它允许访问代码中任何地方的属性和方法。
class House:
def __init__(self, color):
self.color = color
house_public = House('Blue public')
print(house_public.color)
# output: Blue public
受保护
受保护的访问修饰符的功能与Java语言的功能不同,它在Python语言中按照惯例或标准存在。它表示为“ _” 。要用Python语言声明,我们将其添加为属性或方法的前缀。但这并不意味着它受到保护,而是它是开发人员中的惯例。以指示属性和方法的访问的方式,仅在子类中。
class House:
def __init__(self, color):
self._color = color
def print_color(self):
print(f'Color this house is {self._color}')
house_protected = House('Blue protected')
print(house_protected._color)
print(house_protected.print_color())
# output : Blue protected
# Color this house is Blue protected
# None
私人
现在我们拥有私有它也可以作为Python语言约定。它表示为“ __” 。要用Python语言声明,我们将其添加为属性或方法的前缀。但这并不意味着它是私人的,它可以作为开发人员之间的惯例。以指示属性和方法访问的方式,仅在定义的类中。
class House:
def __init__(self, color):
self.__color = color
def print_color(self):
print(f'Color this house is {self.__color}')
但是,因为私人也是一个约定,因此发生了错误。这是因为当我们用“ __” 声明属性时,语言知道我们正在使用私人属性并在其名称上执行转换。称为“名称杂交”,它添加了“ _” 前缀,使其仅在类中访问,而不是像Java语言一样私有。
try:
house_private = House('Blue private')
print(house_private.__color)
print(house_private.print_color())
except Exception as e:
print(e)
#output: 'House' object has no attribute '__color'
要访问修改后的名称,您必须以与名称Mangling返回相同的方式传递。
class House:
def __init__(self, color):
self.__color = color
def print_color(self):
print(f'Color this house is {self.__color}')
try:
house_private = House('Blue private')
print(house_private._House__color)
print(house_private.print_color())
except Exception as e:
print(e)
# output:
# Blue private
# Color this house is Blue private
# None
封装
作为OOP的主要基础之一,封装旨在确保班级内部属性和方法的完整性。除了改进代码维护外,因为必要的更改仅是类的内部,这带来了一个受控的环境,其更改不会影响外部代码。
错误
在此阶段,这并不意味着它是错误的,而是因为我们宣布私人属性。我们不想使用“名称杂货”,并且能够使用封装。
class Car:
def __init__(self, model, motor):
self.model = model
self.__motor = motor
car = Car('Ferrari', 'V8')
try:
print(
car.model,
car.motor,
)
except Exception as e:
print(e)
# output: 'Car' object has no attribute 'motor'
正确
getters和setter受控制和安全的方法,以便我们可以访问(获取)并修改(设置)将在类中分配的数据。
-
getter:返回分配的值。不必直接处理类属性。创建保护层。在此示例中,我将使用称为 @property 的装饰器。此装饰器允许定义的方法可以访问属性。
-
设置器:更改分配的值。它的原理是为属性定义一个新值。在此示例中,我将使用称为 @setter 的装饰器。该装饰器允许定义的方法修改属性。
class Car:
def __init__(self, model, motor):
self.model = model
self.__motor = motor
#Getter
@property
def motor(self):
return self.__motor
#Setter
@motor.setter
def motor(self, motor):
self.__motor = motor
car = Car('Ferrari', 'V8')
print(
car.model,
car.motor,
)
# output: Ferrari V8
方法超载
方法过载将在类中为同一类创建多个功能(方法)的可能性。不需要为不同功能创建新类。但是,用Python语言,它不像其他语言那样支持超载。在下面,我创建了一个班级。但是请注意,捕获该错误表明缺少论点。因为下一个方法覆盖了上一个。
class UnifyStrings:
def unify(self, first_text, second_text):
return first_text + second_text
def unify(self, first_test, second_text, separator):
group_text_input = [first_test, second_text]
return separator.join(group_text_input)
try:
all_join = UnifyStrings()
print(all_join.unify("Hey", "Python"))
print(all_join.unify("Hey", "Python", ", "))
except Exception as e:
print(e)
# output: UnifyStrings.unify() missing 1 required positional argument: 'separator'
协会
关联是一个解释对象之间关系的概念。至于两个对象或类别可以共享信息的关系。
在代码中注意,我要定义两个具有其特征的类别
class Kitchen:
def __init__(self, boss_kitchen, time):
self.boss_kitchen = boss_kitchen
self.time = time
self._order = None
@property
def order(self):
return self._order
@order.setter
def order(self, order):
self._order = order
class Request:
def __init__(
self,
order_number,
customer_name,
hamburguer,
observation,
):
self.order_number = order_number
self.customer_name = customer_name
self.hamburguer = hamburguer
self.observation = observation
def deliver_kitchen_order(self):
return f'Order number: {self.order_number}\n'\
f'Customer Name: {self.customer_name}\n'\
f'Hamburg: {self.hamburguer}\n'\
f'Note: {self.observation}\n'
我实例化了厨房课程,获得了厨师和他的时间。
kitchen = Kitchen('Frinaldio', 'nocturnal')
print(kitchen.boss_kitchen, kitchen.time)
# output: Frinaldio nocturnal
此时,客户到达并下订单。以与上一类相同的方式,我创建了一个具有您的订单定义的新对象。
request1 = Request(
order_number=1671,
customer_name='Rorismaldo Cruz',
hamburguer='X-All',
observation='No onion',
)
print(
request1.order_number,
request1.customer_name,
request1.hamburguer,
request1.observation,
)
# output: 1671 Rorismaldo Cruz X-All No onion
但是订单必须去某个地方,厨房收到订单。在厨房课程中注意,我只有设置器和Getter方法。我将分配一个类别的订单,然后将订单关联到厨房,在那里它将接收订单类的方法,即“ degar_order_cozinha()”。然后请注意,我在厨房对象上使用了这种相关方法。我在哪里可以访问订单属性。
kitchen.order = request1
print(kitchen.order.deliver_kitchen_order())
# output: Order number: 1671
#Customer Name: Rorismaldo Cruz
#Hamburg: X-All
#Note: No onion
kitchen = Kitchen('Crilzancar', 'Morning')
print(kitchen.boss_kitchen, kitchen.time)
# output: Crilzancar Morning
request123 = Request(
order_number=9012,
customer_name='Jorolmir Cunha',
hamburguer='X-Egg',
observation='No egg',
)
print(
request123.order_number,
request123.customer_name,
request123.hamburguer,
request123.observation,
)
# output: 9012 Jorolmir Cunha X-Egg No egg
kitchen.order = request123
print(kitchen.order.deliver_kitchen_order())
# output: Order number: 9012
# Customer Name: Jorolmir Cunha
# Hamburg: X-Egg
# Note: No egg
聚合
在聚合中,一类在其结构中具有其他类别。
# This step below I just created to simulate an order time and then the time it will take to prepare
import time
import datetime
named_tuple = time.localtime()
year = named_tuple.tm_year
month = named_tuple.tm_mon
day = named_tuple.tm_mday
hour = named_tuple.tm_hour
minute = named_tuple.tm_min
second = named_tuple.tm_sec
start_request_time = datetime.datetime(year, month, day, hour, minute, second)
final_order_time = start_request_time + datetime.timedelta(minutes = 40)
print(start_request_time)
print(final_order_time)
# output: 2023-05-21 15:10:29
# 2023-05-21 15:50:29
class Kitchen:
def __init__(self, head_kitchen):
self.head_kitchen = head_kitchen
self._orders = []
def new_order(self, order):
self._orders.append(order)
def kitchen_orders(self):
for order in self._orders:
print(
f'Order number: {order.order_number}\n'\
f'Customer Name: {order.customer_name}\n'\
f'Head of Kitchen: {self.head_kitchen}\n'\
f'Hamburg: {order.hamburguer}\n'\
f'Note: {order.observation}\n'
f'Request Time: {start_request_time}\n'
f'Time ready: {final_order_time}\n'
)
class Request:
def __init__(
self,
order_number,
customer_name,
hamburguer,
observation,
):
self.order_number = order_number
self.customer_name = customer_name
self.hamburguer = hamburguer
self.observation = observation
再次在“哈哈哈”厨房情况下。我要定义一个新的厨房对象。
kitchen = Kitchen('Terequelzio')
但是,想象一下这个厨房收到了几个要求,而不是关联。我将在一个类中团结几个对象,在那里我可以在单个类中使用它们的方法和属性。对于厨房物体,您将可以访问到达的订单,无论厨房内的人都会看到订单的特征并开始准备。
request1 = Request(
order_number=1671,
customer_name='Rorismaldo Cruz',
hamburguer='X-All',
observation='No onion',
)
request2 = Request(
order_number=9012,
customer_name='Jorolmir Cunha',
hamburguer='X-Egg',
observation='No egg',
)
kitchen.new_order(request1)
kitchen.new_order(request2)
kitchen.kitchen_orders()
# output:
# Order number: 1671
# Customer Name: Rorismaldo Cruz
# Head of Kitchen: Terequelzio
# Hamburg: X-All
# Note: No onion
# Request Time: 2023-05-21 15:10:29
# Time ready: 2023-05-21 15:50:29
# Order number: 9012
# Customer Name: Jorolmir Cunha
# Head of Kitchen: Terequelzio
# Hamburg: X-Egg
# Note: No egg
# Request Time: 2023-05-21 15:10:29
# Time ready: 2023-05-21 15:50:29
作品
构图是关于将类与其他类相结合而无需父级(主类)的类。这样,我们就可以拥有一个看起来像构建基础的课程。我们将其作为基础创建,而在其他类中,我们可以逐件组成我们想要的结构。
# This step below I just created to simulate an order time and then the time it will take to prepare
import time
import datetime
named_tuple = time.localtime()
year = named_tuple.tm_year
month = named_tuple.tm_mon
day = named_tuple.tm_mday
hour = named_tuple.tm_hour
minute = named_tuple.tm_min
second = named_tuple.tm_sec
start_request_time = datetime.datetime(year, month, day, hour, minute, second)
final_order_time = start_request_time + datetime.timedelta(minutes = 40)
print(start_request_time)
print(final_order_time)
# output:
# 2023-05-21 15:10:29
# 2023-05-21 15:50:29
class Potato:
def __init__(self, size, quantity):
self.size = size
self.quantity = quantity
class Hamburguer:
def __init__(self, size, quantity):
self.size = size
self.quantity = quantity
class Soda:
def __init__(self, size, quantity):
self.size = size
self.quantity = quantity
class Request:
def __init__(self, customer_name):
self.customer_name = customer_name
self._potato = None
self._hamburguer = None
self._soda = None
@property
def potato(self):
return self._potato
@potato.setter
def potato(self, potato):
self._potato = potato
@property
def hamburguer(self):
return self._hamburguer
@hamburguer.setter
def hamburguer(self, hamburguer):
self._hamburguer = hamburguer
@property
def soda(self):
return self._soda
@soda.setter
def soda(self, soda):
self._soda = soda
def add_potato(self, quantity, size):
self.potato = Potato(quantity, size)
def add_hamburguer(self, quantity, size):
self.hamburguer = Hamburguer(quantity, size)
def add_soda(self, quantity, size):
self.soda = Soda(quantity, size)
def show_order(self):
print(
f'Customer Name: {self.customer_name}\n'\
f'Burger: {self.hamburguer.quantity}| {self.hamburguer.size}\n'\
f'Potato: {self.potato.quantity}| {self.potato.size}\n'\
f'Soda: {self.soda.quantity}| {self.soda.size}\n'\
f'Request Time: {start_request_time}\n'
f'Time ready: {final_order_time}\n'
)
构图概念是通过一堂课使用的最有趣的概念之一。基类(顺序)可以使用您的定义。这非常好,因为您避免在课程中添加许多参数。以有组织的方式,每个功能将被隔离。我将能够部分组成。如下面的顺序示例。
request1 = Request(
customer_name='Rorismaldo Cruz',
)
request1.add_potato(2, 'medium')
request1.add_hamburguer(2, 'medium')
request1.add_soda(2, 'medium')
request1.show_order()
# output:
# Customer Name: Rorismaldo Cruz
# Burger: medium| 2
# Potato: medium| 2
# Soda: medium| 2
# Request Time: 2023-05-21 15:10:29
# Time ready: 2023-05-21 15:50:29
request1 = Request(customer_name='Mericliendes Bento')
request1.add_potato(8, 'small')
request1.add_hamburguer(2, 'big')
request1.add_soda(3, 'small')
request1.show_order()
# output:
# Customer Name: Mericliendes Bento
# Burger: big| 2
# Potato: small| 8
# Soda: small| 3
# Request Time: 2023-05-21 15:10:29
# Time ready: 2023-05-21 15:50:29
遗产
继承带来了代码重复使用的主要点。使用下面的汽车类示例,我们在示例中传递了其特征。然后,我们声明了一个新课程,例如Micro_car,Sedans,sports_car,它们正在从汽车班上借用其特征。然后,我们可以使用这些类实例化新对象。
# parent class
class Car:
def __init__(self, modelo):
self.modelo = modelo
def print_car(self):
print("")
#child class
class Micro_Car(Car):
def print_car(self):
print(f"Your microcar is : {self.modelo}")
#child class
class Sedans(Car):
def print_car(self):
print(f"Your sedan is: {self.modelo}")
#child class
class Sports_Cars(Car):
def print_car(self):
print(f"Your Sport Car is: {self.modelo}")
#We create the object
bond_bug = Micro_Car("Bond Bug")
fiat_cinquecento= Sedans("Fiat Cinquecento")
porsche_911= Sports_Cars("Porsche 911")
bond_bug.print_car()
fiat_cinquecento.print_car()
porsche_911.print_car()
# output:
# Your microcar is : Bond Bug
# Your sedan is: Fiat Cinquecento
# Your Sport Car is: Porsche 911
多态性
多态性是另一个面向对象的概念,我们如何修改在父类中具有其定义的子类方法。通过这种方式,我们通过继承重复了已经定义的方法。子类中的修改方法结构
# Parent class
class Time_Activite:
def time(self):
pass
# Child class
class Total_Time_kilimeter(Time_Activite):
def __init__(self, total_kilimeter, time_input):
self.total_kilimeter = total_kilimeter
self.time_input = time_input
# Method modification
def time(self):
#Note that the results are different, being able to create the same methods more for different behaviors
return f'Your activite => Kilimeter: {self.total_kilimeter} | Time: {self.time_input}'
# Child class
class Time_Per_Kilimeter(Time_Activite):
def __init__(self, total_kilimeter, time_input):
self.total_kilimeter = total_kilimeter
self.time_input = time_input
# Method modification
def time(self):
time = (self.time_input * 60)
time = (time / self.total_kilimeter)
time = (time / 60)
#Note that the results are different, being able to create the same methods more for different behaviors
return f'Your time per kilometer: {time} minutes'
results = [Total_Time_kilimeter(5, 20), Time_Per_Kilimeter(7, 35)]
for result in results:
print(result.time())
# output:
# Your activite => Kilimeter: 5 | Time: 20
# Your time per kilometer: 5.0 minutes
界面
Python语言中的接口没有类型的实现的Java语言的结构。通常,使用属性和方法将其视为示例结构,但缺乏严格的验证。请参阅下面的跑步和山地自行车课。这些类正在从Interface_sport接口中获得示例类。使用activate_activity函数您可以利用使用start_activite方法声明的接口。
class InterfaceSport:
def start_activite(self):
pass
class Run(InterfaceSport):
def start_activite(self):
return "Race start, let's go !!!"
class MountainBike(InterfaceSport):
def start_activite(self):
return "MTB start, let's go !!!"
def activate_activity(activity):
print(activity.start_activite())
run = Run()
mtb = MountainBike()
activate_activity(run)
activate_activity(mtb)
# output:
# Race start, let's go !!!
# MTB start, let's go !!!
评论
感谢您阅读这篇文章。希望我能帮助您理解。任何代码或文本错误,请随时返回。不要忘记离开这样的人,以便您可以吸引更多的人。
资源
在这里,我离开了上面的代码笔记本。如果您从未使用过Jupyter笔记本。我建议下载文件并将其上传到Google驱动器,然后使用Google Colab打开。单击以运行您将避免创建环境,很快您将能够测试代码。