当前位置: 首页 > 文档资料 > Python 面向对象 >

建筑模块(Building Blocks)

优质
小牛编辑
131浏览
2023-12-01

在本章中,我们将详细讨论面向对象的术语和编程概念.Class只是一个实例的工厂。 该工厂包含描述如何制作实例的蓝图。 从类构造实例或对象。 在大多数情况下,我们可以有一个以上的类实例。 每个实例都有一组属性,这些属性在类中定义,因此特定类的每个实例都应具有相同的属性。

类捆绑:行为和状态

类可以让您将对象的行为和状态捆绑在一起。 请注意以下图表以便更好地理解 -

捆绑

在讨论课程包时,以下几点值得注意 -

  • 单词behaviorfunction相同 - 它是执行某些操作(或实现行为)的一段代码

  • 单词statevariables相同 - 它是一个在类中存储值的地方。

  • 当我们一起断言一个类行为和状态时,它意味着一个类打包函数和变量。

类具有方法和属性

在Python中,创建方法定义了一个类行为。 word方法是给定在类中定义的函数的OOP名称。 总结一下 -

  • Class functions - 是methods同义词

  • Class variables - 是name attributes.同义词name attributes.

  • Class - 具有确切行为的实例的蓝图。

  • Object - 类的一个实例,执行类中定义的功能。

  • Type - 表示实例所属的类

  • Attribute - 任何对象值:object.attribute

  • Method - 类中定义的“可调用属性”

例如,请注意以下代码 -

var = “Hello, John”
print( type (var)) # ‘str’> or <class 'str'>
print(var.upper()) # upper() method is called, HELLO, JOHN

创建和实例化

以下代码显示了如何创建我们的第一个类,然后创建它的实例。

class MyClass(object):
   pass
# Create first instance of MyClass
this_obj = MyClass()
print(this_obj)
# Another instance of MyClass
that_obj = MyClass()
print (that_obj)

在这里,我们创建了一个名为MyClass的类,它不执行任何任务。 MyClass类中的参数object涉及类继承,将在后面的章节中讨论。 pass上面的代码表明这个块是空的,也就是说它是一个空类定义。

让我们创建一个MyClass()类的实例this_obj并将其打印出来 - 如图所示 -

<__main__.MyClass object at 0x03B08E10>
<__main__.MyClass object at 0x0369D390>

在这里,我们创建了一个MyClass.实例MyClass. 十六进制代码指的是存储对象的地址。 另一个例子指向另一个地址。

现在让我们在类MyClass()定义一个变量,并从该类的实例中获取变量,如下面的代码所示 -

class MyClass(object):
   var = 9
# Create first instance of MyClass
this_obj = MyClass()
print(this_obj.var)
# Another instance of MyClass
that_obj = MyClass()
print (that_obj.var)

输出 (Output)

执行上面给出的代码时,您可以观察到以下输出 -

9
9

由于实例知道它实例化了哪个类,因此当从实例请求属性时,实例会查找属性和类。 这称为attribute lookup.

实例方法

类中定义的函数称为method. 实例方法需要一个实例才能调用它并且不需要装饰器。 创建实例方法时,第一个参数始终为self. 虽然我们可以通过任何其他名称来调用它(self),但建议使用self,因为它是一个命名约定。

class MyClass(object):
   var = 9
   def firstM(self):
      print("hello, World")
obj = MyClass()
print(obj.var)
obj.firstM()

输出 (Output)

执行上面给出的代码时,您可以观察到以下输出 -

9
hello, World

请注意,在上面的程序中,我们定义了一个以self作为参数的方法。 但我们不能调用该方法,因为我们没有声明任何参数。

class MyClass(object):
   def firstM(self):
      print("hello, World")
      print(self)
obj = MyClass()
obj.firstM()
print(obj)

输出 (Output)

执行上面给出的代码时,您可以观察到以下输出 -

hello, World
<__main__.MyClass object at 0x036A8E10>
<__main__.MyClass object at 0x036A8E10>

封装(Encapsulation)

封装是OOP的基础之一。 OOP使我们能够隐藏对象内部工作的复杂性,这对开发人员有以下几种方式的好处 -

  • 在不知道内部结构的情况下简化并易于理解使用对象。

  • 任何变化都可以轻松管理。

面向对象的编程在很大程度上依赖于封装。 术语封装和抽象(也称为数据隐藏)通常用作同义词。 它们几乎是同义词,因为抽象是通过封装实现的。

封装为我们提供了限制对某些对象组件的访问的机制,这意味着无法从对象定义的外部看到对象的内部表示。 通常通过特殊方法( GettersSetters.来访问此数据Setters.

此数据存储在实例属性中,可以在类外的任何位置进行操作。 为了保护它,只能使用实例方法访问该数据。 不允许直接访问。

class MyClass(object):
   def setAge(self, num):
      self.age = num
   def getAge(self):
      return self.age
zack = MyClass()
zack.setAge(45)
print(zack.getAge())
zack.setAge("Fourty Five")
print(zack.getAge())

输出 (Output)

执行上面给出的代码时,您可以观察到以下输出 -

45
Fourty Five

只有在数据正确且有效的情况下,才应使用异常处理结构存储数据。 正如我们上面所看到的,对setAge()方法的用户输入没有限制。 它可以是字符串,数字或列表。 因此,我们需要检查上面的代码以确保存储的正确性。

class MyClass(object):
   def setAge(self, num):
      self.age = num
   def getAge(self):
      return self.age
zack = MyClass()
zack.setAge(45)
print(zack.getAge())
zack.setAge("Fourty Five")
print(zack.getAge())

Init构造函数

只要实例化类的对象,就会隐式调用__ init __方法。这将初始化对象。

x = MyClass()

上面显示的代码行将创建一个新实例,并将此对象分配给局部变量x。

实例化操作(即calling a class object )创建一个空对象。 许多类喜欢创建具有针对特定初始状态定制的实例的对象。 因此,一个类可以定义一个名为'__init __()'的特殊方法,如图所示 -

def __init__(self):
   self.data = []

Python在实例化期间调用__init__来定义在实例化类时可能发生的附加属性,该属性可能为该对象设置一些起始值或运行实例化时所需的例程。 因此,在此示例中,可以通过以下方式获取新的初始化实例:

x = MyClass()

__init __()方法可以具有单个或多个参数,以获得更大的灵活性。 init代表初始化,因为它初始化实例的属性。 它被称为类的构造函数。

class myclass(object):
   def __init__(self,aaa, bbb):
      self.a = aaa
      self.b = bbb
x = myclass(4.5, 3)
print(x.a, x.b)

输出 (Output)

4.5 3

类属性

类中定义的属性称为“类属性”,函数中定义的属性称为“实例属性”。 在定义时,这些属性不以self为前缀,因为它们是类的属性而不是特定实例的属性。

类属性(className.attributeName)以及类的实例(inst.attributeName)可以访问类属性。 因此,实例可以访问实例属性和类属性。

>>> class myclass():
   age = 21
>>> myclass.age
21
>>> x = myclass()
>>> x.age
21
>>>

可以在实例中覆盖类属性,即使它不是打破封装的好方法。

Python中有属性的查找路径。 第一个是在类中定义的方法,然后是它上面的类。

>>> class myclass(object):
   classy = 'class value'
>>> dd = myclass()
>>> print (dd.classy) # This should return the string 'class value'
class value
>>>
>>> dd.classy = "Instance Value"
>>> print(dd.classy) # Return the string "Instance Value"
Instance Value
>>>
>>> # This will delete the value set for 'dd.classy' in the instance.
>>> del dd.classy
>>> >>> # Since the overriding attribute was deleted, this will print 'class
value'.
>>> print(dd.classy)
class value
>>>

我们正在覆盖实例dd中的'classy'类属性。 当它被覆盖时,Python解释器会读取被覆盖的值。 但是一旦使用'del'删除新值,实例中就不再出现被覆盖的值,因此查找会超出上面的级别并从类中获取。

使用类和实例数据

在本节中,让我们了解类数据如何与实例数据相关。 我们可以将数据存储在类或实例中。 当我们设计一个类时,我们决定哪个数据属于实例,哪些数据应该存储到整个类中。

实例可以访问类数据。 如果我们创建多个实例,那么这些实例可以访问它们各自的属性值以及整个类数据。

因此,类数据是在所有实例之间共享的数据。 请注意下面给出的代码以获得更好的无效 -

class InstanceCounter(object):
   count = 0 # class attribute, will be accessible to all instances
   def __init__(self, val):
      self.val = val
      InstanceCounter.count +=1 # Increment the value of class attribute, accessible through class name
# In above line, class ('InstanceCounter') act as an object
   def set_val(self, newval):
      self.val = newval
   def get_val(self):
      return self.val
   def get_count(self):
      return InstanceCounter.count
a = InstanceCounter(9)
b = InstanceCounter(18)
c = InstanceCounter(27)
for obj in (a, b, c):
   print ('val of obj: %s' %(obj.get_val())) # Initialized value ( 9, 18, 27)
   print ('count: %s' %(obj.get_count())) # always 3

输出 (Output)

val of obj: 9
count: 3
val of obj: 18
count: 3
val of obj: 27
count: 3

简而言之,类属性对于类的所有实例都是相同的,而实例属性对于每个实例都是特定的。 对于两个不同的实例,我们将有两个不同的实例属性。

class myClass:
   class_attribute = 99
   def class_method(self):
      self.instance_attribute = 'I am instance attribute'
print (myClass.__dict__)

输出 (Output)

执行上面给出的代码时,您可以观察到以下输出 -

{'__module__': '__main__', 'class_attribute': 99, 'class_method': <function myclass.class_method="" at="">, '__dict__': <attribute of="" objects="">, '__weakref__': <attribute of="" objects="">, '__doc__': None}
</attribute></attribute></function>

实例属性myClass.__dict__如图所示 -

>>> a = myClass()
>>> a.class_method()
>>> print(a.__dict__)
{'instance_attribute': 'I am instance attribute'}