在本章中,我们将详细讨论面向对象的术语和编程概念.Class只是一个实例的工厂.该工厂包含描述
如何制作实例的蓝图.从类构造实例或对象.在大多数情况下,我们可以有一个以上的类实例.每个实例都有一组属性,这些属性在类中定义,因此特定类的每个实例都应具有相同的属性.
一个类可以让你将对象的行为和状态捆绑在一起.观察下面的
以便更好地理解 :
在讨论课程包 : 去时,以下几点值得注意;
单词行为与函数相同 - 它是一段代码(或实现某种行为)
单词 state 与变量相同 - 它是一个在一个类中存储值的地方.
当我们声明一个类行为和状态在一起,这意味着一个类打包函数和变量.
在Python中,创建方法定义了一个类行为. word方法是给定在类中定义的函数的OOP名称.总结 :
类函数 : 是方法的同义词
类变量 : 是名称属性的同义词.
Class : 具有确切行为的实例的蓝图.
对象 : 该类的一个实例,执行该类中定义的功能.
类型 : 表示实例所属的类
属性 : 任何对象值:object.attribute
方法 : 在类中定义的"可调用属性"
观察以下代码片段,例如 :
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 涉及类继承,将在后面的章节中讨论.上面代码中的传递表示此块为空,即它是一个空类定义.
让我们创建一个实例 this_obj MyClass()类并打印如下所示 :
<__main__.MyClass object at 0x03B08E10> <__main__.MyClass object at 0x0369D390>
这里,我们创建了 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)
执行代码时可以观察到以下输出给出上面和下面;
9 9
As实例知道它实例化了哪个类,因此当从实例请求属性时,实例会查找属性和类.这称为属性查找.
在类中定义的函数称为方法.实例方法需要一个实例才能调用它并且不需要装饰器.在创建实例方法时,第一个参数始终是 self.虽然我们可以通过任何其他名称来调用它(self),但建议使用self,因为它是一个命名约定.
class MyClass(object): var = 9 def firstM(self): print("hello, World") obj = MyClass() print(obj.var) obj.firstM()
执行上面给出的代码时,您可以观察到以下输出;
9 hello,World
请注意,在上面的程序中,我们使用self作为参数定义了一个方法.但我们无法调用该方法,因为我们没有声明任何参数.
class MyClass(object): def firstM(self): print("hello, World") print(self) obj = MyClass() obj.firstM() print(obj)
执行上面给出的代码时,您可以观察到以下输出;
hello,World < __ main __.MyClass对象位于0x036A8E10> < __ main __.MyClass对象位于0x036A8E10>
封装是OOP的基础之一. OOP使我们能够隐藏对象内部工作的复杂性
,这对开发人员在
中有利于以下方式 :
在不知道内部结构的情况下简化并易于理解使用对象.
任何更改都可以轻松管理.
面向对象的编程在很大程度上依赖于封装.术语封装和抽象(也称为数据隐藏)通常用作同义词.它们几乎是同义词,因为抽象是通过封装实现的.
封装为我们提供了限制访问某些对象的
组件的机制,这意味着内部表示从对象定义外部看不到对象.通常通过特殊的
方法减去对这些数据的访问; Getters 和 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())
当您执行上面给出的代码时,您可以观察到以下输出;
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__方法,这将初始化该对象。
x = MyClass()
上面显示的代码行将创建一个新实例,并将此对象分配给
局部变量x.
实例化操作,即调用类对象,创建一个空对象.许多类喜欢创建具有针对特定初始状态定制的实例的对象.因此,类可以定义一个名为'__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)
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
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__)
执行上面给出的代码时,您可以观察到以下输出;
{'__module __:'__ main __','class_attribute':99,'class_method':
实例属性 myClass .__ dict __ as显示 :
>>> a = myClass() >>> a.class_method() >>> print(a.__dict__) {'instance_attribute': 'I am instance attribute'}