Object Oriented Python 简明教程
Object Oriented Python - Building Blocks
在本章中,我们将详细讨论面向对象术语和编程概念。类只是实例的一个工厂。这个工厂包含描述如何创建实例的蓝图。实例或对象是根据类构造的。在大多数情况下,我们可以拥有一个类的多个实例。每个实例都有一组属性,这些属性在类中定义,因此特定类的每个实例都应具有相同的属性。
In this chapter, we will discuss object oriented terms and programming concepts in detail.Class is a just a factory for an instance. This factory contains the blueprint which describes how to make the instances. An instances or object are constructed from the class. In most cases, we can have more than one instances of a class. Every instance has a set of attribute and these attributes are defined in a class, so every instance of a particular class is expected to have the same attributes.
Class Bundles : Behavior and State
一个类可以让你将一个对象的的行为和状态捆绑在一起。观察以下图表以更好地理解 -
A class will let you bundle together the behavior and state of an object. Observe the following diagram for better understanding −

在讨论类捆绑时,以下几点值得注意 -
The following points are worth notable when discussing class bundles −
-
The word behavior is identical to function – it is a piece of code that does something (or implements a behavior)
-
The word state is identical to variables – it is a place to store values within a class.
-
When we assert a class behavior and state together, it means that a class packages functions and variables.
Classes have methods and attributes
在 Python 中,创建方法定义类行为。方法这个词是面向对象编程中给类内部定义的函数的一个名称。总结一下:
In Python, creating a method defines a class behavior. The word method is the OOP name given to a function that is defined within a class. To sum up −
-
Class functions − is synonym for methods
-
Class variables − is synonym for name attributes.
-
Class − a blueprint for an instance with exact behavior.
-
Object − one of the instances of the class, perform functionality defined in the class.
-
Type − indicates the class the instance belongs to
-
Attribute − Any object value: object.attribute
-
Method − a “callable attribute” defined in the class
观察以下代码段以作示例——
Observe the following piece of code for example −
var = “Hello, John”
print( type (var)) # ‘str’> or <class 'str'>
print(var.upper()) # upper() method is called, HELLO, JOHN
Creation and Instantiation
以下代码展示了如何创建我们的第一个类,然后创建它的实例。
The following code shows how to create our first class and then its instance.
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 表明,该块是空的,也就是一个空的类定义。
Here we have created a class called MyClass and which does not do any task. The argument object in MyClass class involves class inheritance and will be discussed in later chapters. pass in the above code indicates that this block is empty, that is it is an empty class definition.
让我们创建一个类 MyClass() 的实例 this_obj 并对其进行打印,如以下所示:
Let us create an instance this_obj of MyClass() class and print it as shown −
<__main__.MyClass object at 0x03B08E10>
<__main__.MyClass object at 0x0369D390>
在此,我们创建了 MyClass. 的一个实例。十六进制代码是指对象存储的地址。另一个实例指向另一个地址。
Here, we have created an instance of MyClass. The hex code refers to the address where the object is being stored. Another instance is pointing to another address.
现在让我们在类 MyClass() 中定义一个变量,并从该类的实例中获取变量,如下面的代码所示:
Now let us define one variable inside the class MyClass() and get the variable from the instance of that class as shown in the following code −
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
执行上述代码时,可以看到以下输出:
You can observe the following output when you execute the code given above −
9
9
由于实例知道自己是通过哪个类实例化,因此当从实例请求属性时,实例会查找属性和类。这称为 attribute lookup.
As instance knows from which class it is instantiated, so when requested for an attribute from an instance, the instance looks for the attribute and the class. This is called the attribute lookup.
Instance Methods
类中定义的函数称为 method. 实例方法需要一个实例才能调用它,并且不需要装饰器。在创建实例方法时,第一个参数始终为 self. 虽然我们可以用任何其他名称调用它(self),但建议使用 self,因为它是一个命名约定。
A function defined in a class is called a method. An instance method requires an instance in order to call it and requires no decorator. When creating an instance method, the first parameter is always self. Though we can call it (self) by any other name, it is recommended to use self, as it is a naming convention.
class MyClass(object):
var = 9
def firstM(self):
print("hello, World")
obj = MyClass()
print(obj.var)
obj.firstM()
Output
执行上述代码时,可以看到以下输出:
You can observe the following output when you execute the code given above −
9
hello, World
请注意,在上面的程序中,我们定义了一个方法,其中 self 为参数。但我们无法调用该方法,因为我们没有向其声明任何参数。
Note that in the above program, we defined a method with self as argument. But we cannot call the method as we have not declared any argument to it.
class MyClass(object):
def firstM(self):
print("hello, World")
print(self)
obj = MyClass()
obj.firstM()
print(obj)
Encapsulation
封装是 OOP 的基本原则之一。OOP 让我们能够隐藏对象的内部工作原理的复杂性,在以下方面对开发人员有利 −
Encapsulation is one of the fundamentals of OOP. OOP enables us to hide the complexity of the internal working of the object which is advantageous to the developer in the following ways −
-
Simplifies and makes it easy to understand to use an object without knowing the internals.
-
Any change can be easily manageable.
面向对象编程严重依赖于封装。术语“封装”和“抽象”(也称为数据隐藏)通常被用作同义词。它们几乎是同义词,因为抽象是通过封装实现的。
Object-oriented programming relies heavily on encapsulation. The terms encapsulation and abstraction (also called data hiding) are often used as synonyms. They are nearly synonymous, as abstraction is achieved through encapsulation.
封装为我们提供了限制对某些对象组件的访问权限的机制,这意味着对象内部表示不能从对象定义外部看到。通常通过特殊方法 Getters 和 Setters. 来访问这些数据
Encapsulation provides us the mechanism of restricting the access to some of the object’s components, this means that the internal representation of an object can’t be seen from outside of the object definition. Access to this data is typically achieved through special methods − Getters and Setters.
这些数据存储在实例属性中,可以从类外的任何地方进行操作。为了保护它,只应使用实例方法访问该数据。禁止直接访问。
This data is stored in instance attributes and can be manipulated from anywhere outside the class. To secure it, that data should only be accessed using instance methods. Direct access should not be permitted.
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
执行上述代码时,可以看到以下输出:
You can observe the following output when you execute the code given above −
45
Fourty Five
应该使用异常处理结构仅在数据正确有效时存储数据。如上所见,对于 setAge() 方法,没有对用户输入的限制。它可以是字符串、数字或列表。因此,我们需要检查上面的代码以确保存储的正确性。
The data should be stored only if it is correct and valid, using Exception handling constructs. As we can see above, there is no restriction on the user input to setAge() method. It could be a string, a number, or a list. So we need to check onto above code to ensure correctness of being stored.
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 Constructor
方法 *init* 会在类对象实例化后立即隐式调用。这将初始化对象。
The *init* method is implicitly called as soon as an object of a class is instantiated.This will initialize the object.
x = MyClass()
上面显示的这一行代码将创建一个新实例,并将该对象分配给局部变量 x。
The line of code shown above will create a new instance and assigns this object to the local variable x.
实例化操作,即 calling a class object ,创建一个空对象。许多类希望使用对象创建一个实例,该实例定制为特定的初始状态。因此,类可以定义一个名为 “ init ()“ 的特殊方法,如下所示 −
The instantiation operation, that is calling a class object, creates an empty object. Many classes like to create objects with instances customized to a specific initial state. Therefore, a class may define a special method named ‘ init() ‘ as shown −
def __init__(self):
self.data = []
Python 在实例化期间调用 init ,定义了一个当类实例化时应该出现的附加属性,该属性可以设置该对象的某些起始值或在实例化时运行所需例程。因此,在此示例中,可以通过以下方法获取一个新的已初始化实例 −
Python calls init during the instantiation to define an additional attribute that should occur when a class is instantiated that may be setting up some beginning values for that object or running a routine required on instantiation. So in this example, a new, initialized instance can be obtained by −
x = MyClass()
方法 init () 可以具有一个或多个参数,来获得更大的灵活性。init 表示初始化,因为它初始化实例的属性。它被称为类的构造器。
The init() method can have single or multiple arguments for a greater flexibility. The init stands for initialization, as it initializes attributes of the instance. It is called the constructor of a class.
class myclass(object):
def __init__(self,aaa, bbb):
self.a = aaa
self.b = bbb
x = myclass(4.5, 3)
print(x.a, x.b)
Class Attributes
类中定义的属性称为“类属性”,而函数中定义的属性称为“实例属性”。在定义时,这些属性没有前缀 self,因为它们是类的属性,而不是特定实例的属性。
The attribute defined in the class is called “class attributes’ and the attributes defined in the function is called ‘instance attributes’. While defining, these attributes are not prefixed by self, as these are the property of the class and not of a particular instance.
类属性可以通过类本身( className.attributeName)以及类的实例(inst.attributeName)来访问。因此,实例既可以访问实例属性,也可以访问类属性。
The class attributes can be accessed by the class itself ( className.attributeName) as well as by the instances of the class (inst.attributeName). So, the instances have access to both the instance attribute as well as class attributes.
>>> class myclass():
age = 21
>>> myclass.age
21
>>> x = myclass()
>>> x.age
21
>>>
类属性可以在实例中被覆盖,虽然这并不是一个打破封装的好方法。
A class attribute can be overridden in an instance, even though it is not a good method to break encapsulation.
Python 中有一个用于查找属性的路径。第一个是在类中定义的方法,然后是其上方的类。
There is a lookup path for attributes in Python. The first being the method defined within the class, and then the class above it.
>>> 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”删除,覆盖的值便不再存在于该实例中,因此查找将向上一个级别并从类中获取它。
We are overriding the ‘classy’ class attribute in the instance dd. When it’s overridden, the Python interpreter reads the overridden value. But once the new value is deleted with ‘del’, the overridden value is no longer present in the instance, and hence the lookup goes a level above and gets it from the class.
Working with Class and Instance Data
在本节中,让我们了解类数据与实例数据的关系。我们可以将数据存储在类中或实例中。在设计类时,我们需要决定哪些数据属于实例,哪些数据应该存储在总体类中。
In this section, let us understand how the class data relates to the instance data. We can store data either in a class or in an instance. When we design a class, we decide which data belongs to the instance and which data should be stored into the overall class.
实例可以访问类数据。如果我们创建多个实例,那么这些实例既可以访问它们各自的属性值,也可以访问总体类数据。
An instance can access the class data. If we create multiple instances, then these instances can access their individual attribute values as well the overall class data.
因此,类数据是所有实例共享的数据。观察下面给出的代码以更好地理解−
Thus, a class data is the data that is shared among all the instances. Observe the code given below for better undersanding −
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
简而言之,类属性对于类的所有实例都是相同的,而实例属性对于每个实例都是特定的。对于两个不同的实例,我们将有两种不同的实例属性。
In short, class attributes are same for all instances of class whereas instance attributes is particular for each instance. For two different instances, we will have two different instance attributes.
class myClass:
class_attribute = 99
def class_method(self):
self.instance_attribute = 'I am instance attribute'
print (myClass.__dict__)