Python面向对象编程(1)

Python面向对象编程

                                                                                                          -----原著:Dusty Phillips

                                                                                                          -------代码实现:王威
                                                                                                          -------2019/2/13
                                                                                                                 转载请注明出处

对象和类

对象是数据及其行为的集合。类是用来描述对象的。

类的创建使用class关键字,类名一般必须遵循标准的Python变量名准则(必须以字母或下划线开头,并只能由字母,下划线或数字组成)。除此之外,Python风格指南(“PEP 8”)建议类名应该用驼峰格式(CamelClass)命名(以大写字母开头,任意后续单词都以大写字母开头)。
class MyFirstClass:
    pass
a = MyFirstClass()
b = MyFirstClass()
print(a)
print(b)
<__main__.MyFirstClass object at 0x0000021A3D23B630>
<__main__.MyFirstClass object at 0x0000021A3D23B5F8>


在上面的例子中,MyFirstClass是一个类(不过这个类没有任何功能),a和b是两个不同的对象,这两个对象属于MyFirstClass类。

添加属性

现在我们有了一个基本的类,但却没有实际用途。它不包含任何数据也不能做任何事。如何向 ‘指定的对象’ 添加属性?
为了做到这一点,我们不需要改变类的定义,可以通过点标记法对实例对象设定‘任意’属性。
class Point:
    pass
p1 = Point()
p1.x = 5
p1.y = 6
p1.z = 7
p1.abc = 8
print(p1.x,p1.y,p1.z,p1.abc)
5 6 7 8

让它做点什么

让对象拥有属性已经很棒了,但是面向对象编程的重点在于不同对象之间的交互。我们感兴趣的是,触发某些行为可以使属性发生变化。现在让我们为类添加一些行为。
class Point:
    def reset(self):
        self.x = 0
        self.y = 0        #属性名任意,只要不违反规则
        
p = Point()
p.reset()
print(p.x,p.y)

#下面的例子更直接
p.x = 1
p.y = 2
print(p.x,p.y)

p.reset()
print(p.x,p.y)
0 0
1 2
0 0


Python中的方法在格式上与函数完全一致。它以def关键字开头,接着是一个空格加方法名,然后是一对括号括起来的参数列表,最终以冒号结尾。下一行是包含方法内部语句的代码块。这些语句可以是任意的Python代码,可以操作对象自身和所有传递给该方法并被视为合适的参数。

和你自己对话

正常函数与方法之间的区别之一是:all方法都有一个必要的参数。依照惯例,这个参数通常命名为self。(当然也可以使用this,that,ustb等任意字母组合,但几乎没有程序员使用除self之外的名字,这是一种编程习惯。)
self参数就是对方法调用对象的引用。我们可以像对其他对象一样访问这一对象的属性和方法。这也是设置self对象的x和y属性是所做的。
注意:
当我们调用p.reset()方法时,我们不需要传递self参数给他。Pyhton自动的帮我们解决这件事。他知道我们正在调用p对象的方法,所以它自动将这个对象传递给这一方法。

不过,方法实际上只是一个发生在类中的函数而已。除了调用对象的方法,我们也可以直接调用类中的函数,同时明确地将对象作为self参数传递:

p = Point()
p.x = 1
p.y = 2
print(p.x,p.y)

Point.reset(p)       #我们将p对象作为self参数传递给reset()方法
print(p.x,p.y)
1 2
0 0

如果我们忘记在类定义的时候加入self参数会怎样?这是Python会抛出一个错误:

class Point():
    def reset():
        pass
p = Point()
p.reset()
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-14-1a8c8d61ef3c> in <module>
      3         pass
      4 p = Point()
----> 5 p.reset()


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

更多参数

如何向一个方法传递多个参数?我们添加一个新的方法,用来将point移动到任意位置,而不仅仅是原点。我们也可以接收另外一个Point对象作为输入,并返回他们之间的距离:
import math

class Point:
    def move(self, x, y):
        self.x = x
        self.y = y
        
    def reset(self):
        self.move(0, 0)
        
    def calculate_distance(self, other_point):
        return math.sqrt(
                 (self.x - other_point.x)**2 + 
                 (self.y - other_point.y )**2 )
    
#使用这个类
point1 = Point()
point2 = Point()    #创建两个对象,都属于Point类

point1.reset()
point2.move(5,0)    #虽然在类内move()方法有self,x,y,三个参数,但在使用时self参数是Python为我们自动解决的,所以只需要传入另外两个参数
print(point2.calculate_distance(point1))
assert (point2.calculate_distance(point1) == 
       point1.calculate_distance(point2))

point1.move(3,4)
print(point1.calculate_distance(point2))
print(point1.calculate_distance(point1))
5.0
4.47213595499958
0.0

assert函数是一个简单的测试工具,如果aeesrt后面语句的结果为False(或者是0,空值,None),那么程序将会退出。在这个例子中,我们用来确保不管是用哪个对象调用另一个对象的calculate_distance方法,结果都是一致的。

初始化对象

如果我们不明确设定Point对象的位置属性x和y,直接用move方法或直接获取他们,我们将会得到一个没有真实位置的错误点。
point = Point()
point.x = 5
print(point.x)

print(point.y)     #Point没有y这个属性,Point类内的x和y是move方法的参数而已。
5



---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-17-8c42d4cc61e3> in <module>
      3 print(point.x)
      4 
----> 5 print(point.y)     #Point没有y这个属性,Point类内的x和y是move方法的参数而已。


AttributeError: 'Point' object has no attribute 'y'

大多数面向对象编程语言都有构造函数(constructor)的概念,是创建对象时进行创建和初始化的特定方法。Python有点不一样,它同时拥有构造函数和初始化方法。除非你需要做一些异乎寻常的事,否则很少用到构造函数,所以我们就先讨论初始化方法。

Python初始化方法和其他的方法不一样,除了他有特殊的名字__init__。开头和结尾的双下划线意味着这是一个特殊的方法,Python解释器会将其作为特例对待。

注意: 永远不要用以双下划线开头和结尾的名字定义你自己的方法。它对Python来说没有任何意义,但是有可能Python设计者会在未来将其作为特殊用途,一旦他们这么做了,你的代码可能会崩溃。
class Point:
    def __init__(self, x, y):
        self.move(x, y)
    
    def move(self, x, y):
        self.x = x
        self.y = y
        
    def reset(self):
        self.move(0, 0)

#构造一个Point
point = Point(3, 5)
print(point.x, point.y)
3 5

如果我们不想让这两个参数是必需的呢?我们可以用与Python函数相似的语法来提供默认参数。关键字参数语法在变量名后面追加一个等号。如果调用对象没有提供这一参数,则会用默认参数代替。变量名在函数内部仍然是可用的,但其值由参数列表指定。
示例:

class Point:
    def __init__(self, x=0, y=0):
        self.move(x, y)
        
    def move(self, x, y):
        self.x = x
        self.y = y
        
    def reset(self):
        self.move(0, 0)

point = Point()
print(point.x, point.y)
point = Point(5)
print(point.x, point.y)
0 0
5 0


                                                                                                                    --------2019/2/13
                                                                                                                       转载请注明出处

由于是直接上传的md文件,所以部分格式看起来不友好。HTML版本的更加友好。需要的私聊即可。

猜你喜欢

转载自blog.csdn.net/weixin_40802676/article/details/87262764