美文网首页
python10 类和对象

python10 类和对象

作者: 巴巴11 | 来源:发表于2020-04-13 22:20 被阅读0次

定义一个叫做 Point 的类将创建了一个类对象(class object)

class Point:
    """Represents a point in 2-D space."""
由于 Point 是定义在顶层的,所以它的“全名”是__main__.Point。

类对象就像是一个用来创建对象的工厂。 要创建一个点,你可以像调用函数那样调用 Point 。
>>> blank = Point()
>>> blank
<__main__.Point object at 0xb7e9d3ac>


属性

可以使用点标记法向一个实例进行赋值操作:
>>> blank.x = 3.0
>>> blank.y = 4.0

使用相同的语法读取一个属性的值:
>>> blank.y
4.0
>>> x = blank.x
>>> x
3.0


可以将一个实例作为参数传递。 例如:
def print_point(p):
    print('(%g, %g)' % (p.x, p.y))
print_point接受一个点作为参数,打印出其在数学中的表示方法。 调用它的时候,你可以将 blank 作为参数传递:
>>> print_point(blank)
(3.0, 4.0)


定义矩阵类

class Rectangle:
    """Represents a rectangle.

    attributes: width, height, corner.
    """

实例化
box = Rectangle()
box.width = 100.0
box.height = 200.0
box.corner = Point()
box.corner.x = 0.0
box.corner.y = 0.0

实例作为返回值
def find_center(rect):
    p = Point()
    p.x = rect.corner.x + rect.width/2
    p.y = rect.corner.y + rect.height/2
    return p

>>> center = find_center(box)
>>> print_point(center)
(50, 100)

对象可变
box.width = box.width + 50
box.height = box.height + 100

复制

别名会降低程序的可读性,因为一个地方的变动可能对另一个地方造成预料之外的影响。 跟踪所有引用同一个对象的变量是非常困难的。

通常用复制对象的方法取代为对象起别名。 copy模块拥有一个叫做 copy 的函数,可以复制任何对象:
>>> p1 = Point()
>>> p1.x = 3.0
>>> p1.y = 4.0

>>> import copy
>>> p2 = copy.copy(p1)
p1和 p2 拥有相同的数据,但是它们并不是同一个 Point 对象。
>>> print_point(p1)
(3, 4)
>>> print_point(p2)
(3, 4)
>>> p1 is p2
False
>>> p1 == p2
False

== 运算符的默认行为和 is 运算符相同; 它检查对象的标识(identity)是否相同,而非对象的值是否相同。

如果你使用 copy.copy 来复制一个 Rectangle , 你会发现它仅仅复制了 Rectangle 对象,但没有复制嵌套的 Point 对象。
>>> box2 = copy.copy(box)
>>> box2 is box
False
>>> box2.corner is box.corner
True
 这个操作叫做浅复制(shallow copy),因为它仅复制了对象以及其包含的引用, 但未复制嵌套的对象。

copy 模块拥有一个叫做 deepcopy 的方法, 它不仅可以复制一个对象,还可以复制这个对象所引用的对象, 甚至可以复制这个对象所引用的对象所引用的对象,这个操作叫做深复制(deep copy)。
>>> box3 = copy.deepcopy(box)
>>> box3 is box
False
>>> box3.corner is box.corner
False
box3和 box 是完全互不相干的对象。
 如果你访问一个不存在的属性,你会得到 Attributeerror 的错误提示:
>>> p = Point()
>>> p.x = 3
>>> p.y = 4
>>> p.z
AttributeError: Point instance has no attribute 'z'

如果你不确定一个对象的类型,你可以询问:
>>> type(p)
<class '__main__.Point'>

你也可以用 isinstance 来检查某个对象是不是某个类的实例。
>>> isinstance(p, Point)
True

如果你不确定一个对象是否拥有某个属性, 你可以使用内置函数 hasattr 检查:
>>> hasattr(p, 'x')
True
>>> hasattr(p, 'z')
False
第一个参数可以是任何对象; 第二个参数是一个字符串,代表了某个属性的名字。

你也可以使用 try 语句来检查某个对象是不是有你需要的属性:
try:
    x = p.x
except AttributeError:
    x = 0


Python 是一门面向对象的编程语言

类和函数:

class Time:
    """Represents the time of day."""

def print_time(time):
    print('%.2d:%.2d:%.2d' % (time.hour, time.minute, time.second))

类和方法:

将 print_time 变成一个方法,我们只需要将函数定义移到类定义里面即可。注意缩进 的变化。

class Time:
    def print_time(time):
        print('%.2d:%.2d:%.2d' % (time.hour, time.minute, time.second))
现在有两种方法可以调用print_time。第一种(也是不常用的)是使用函数的语法:

>>> Time.print_time(start)
09:45:00
在这个点标记法的用法中,Time 是类的名字,print_time是方法的名字。start 是传递的参数。

第二种语法(也更简洁)是使用方法语法:

>>> start.print_time()
09:45:00
在这个点标记法的用法中,print_time是方法的名称,然后 start 是调用方法的对象 ,被称为主语(subject)。就像一个句子的主语是句子的核心,方法的主语也是方 法作用的主要对象。

在方法中,主语被赋值为第一个参数,所以在这里 start 被赋值给 time 上了。

根据约定,方法的第一个参数写作 self ,所以print_time写成这样更常见:

class Time:
    def print_time(self):
        print('%.2d:%.2d:%.2d' % (self.hour, self.minute, self.second))

init方法:

是一个特殊的方法,当一个对象初始化的时候调 用。

# inside class Time:

    def __init__(self, hour=0, minute=0, second=0):
        self.hour = hour
        self.minute = minute
        self.second = second

通常__init__方法的参数和属性的名称一样。
self.hour = hour

str方法:

特殊方法,返回一个对象的字符串表现形式
# inside class Time:

    def __str__(self):
        return '%.2d:%.2d:%.2d' % (self.hour, self.minute, self.second)

当你打印一个对象,Python 调用 str 方法:

>>> time = Time(9, 45)
>>> print(time)
09:45:00

运算符重载:

通过定义其它的一些特殊方法,你可以在程序员自定义类型上指定运算符的行为。 例如,如果你为 Time 类定义了一个叫__add__的方法,你就可以在 Time 对象上使用 + 运算符。

可以大致像这样定义:

# inside class Time:

    def __add__(self, other):
        seconds = self.time_to_int() + other.time_to_int()
        return int_to_time(seconds)
下面是使用方式:
>>> start = Time(9, 45)
>>> duration = Time(1, 35)
>>> print(start + duration)
11:20:00
当你在 Time 对象上应用 + 运算符,Python 会调用__add__。 当你打印结果时,Python 会调用__str__。

类型分发(type-based dispatch)
在上一节中,我们将两个 Time 对象相加,但是你还会想要将一个整数与 Time 对象相加。下面这个版本的 add 会检查 other 的类型,并相应地调用 add_time 或者 increment :

# inside class Time:

    def __add__(self, other):
        if isinstance(other, Time):
            return self.add_time(other)
        else:
            return self.increment(other)

    def add_time(self, other):
        seconds = self.time_to_int() + other.time_to_int()
        return int_to_time(seconds)

    def increment(self, seconds):
        seconds += self.time_to_int()
        return int_to_time(seconds)
内建函数 isinstance 接受一个值和一个类对象,如果值是这个类的实例则返回 True 。

如果 other 是一个 Time 对象,__add__调用add_time。 否则它假设参数是一个数字然后调用 increment 。 这个操作被称为类型分发(type-based dispatch),因为它根据参数的 类型将计算任务分发给不同的方法。

下面是一些在不同类型上使用 + 运算符的例子:

>>> start = Time(9, 45)
>>> duration = Time(1, 35)
>>> print(start + duration)
11:20:00
>>> print(start + 1337)
10:07:17
不幸的是,这个加法的实现没有交换性(commutative)。如果第一个运算数是一个整数,你会得到:

>>> print(1337 + start)
TypeError: unsupported operand type(s) for +: 'int' and 'instance'
问题在于,我们不是让一个 Time 对象去加一个整数,而是让一个整数去加一个 Time 对 象,但是Python不知道怎样去做。不过这个问题有一个优雅的解决方案:特殊方法 __radd__ ,表示“右手加法”。当一个 Time 对象在 + 运算符的右手边出现时,调用这个方法。下面是定义:

# inside class Time:

    def __radd__(self, other):
        return self.__add__(other)
接着是使用方法:

>>> print(1337 + start)
10:07:17
如果你不确定一个对象是否应该有某个属性,你可以使用内建函数 `hasattr` (参见[调试](https://codingpy.com/books/thinkpython2/15-classes-and-objects.html#hasattr)一节)。

另一种访问对象属性的方法是使用内建函数 `vars` ,它接受一个对象,并返回一个将属性名称(字符串形式)到对应值的字典:
>>> p = Point(3, 4)
>>> vars(p)
{'y': 4, 'x': 3}
</pre>

定义下面这段代码,可能对调试非常有用:
def print_attributes(obj):
    for attr in vars(obj):
        print(attr, getattr(obj, attr))
</pre>

`print_attributes`遍历一个对象的字典,然后打印每个属性的名称和对应的值。

内建函数 `getattr` 接受一个对象和一个属性名称(字符串)作为参数,然后返回该属性的值。

相关文章

  • python10 类和对象

    定义一个叫做 Point 的类将创建了一个类对象(class object) 属性 定义矩阵类 对象可变box.w...

  • 对象、类对象和元类对象

    http://www.tuicool.com/articles/mmyuUr http://blog.csdn.n...

  • python 类和对象

    类和对象 目标 类和对象的概念 类和对象的关系 类的设计 01. 类和对象的概念 类 和 对象 是 面向对象编程的...

  • 类,类对象和实例对象

    Python 的类定义写完之后就成了一个类对象,而引用这个类对象的就是实例对象。 类中定义的属性和方法都是静态属性...

  • 面相对象-02类和对象

    类和对象 目标 ●类和对象的概念●类和对象的关系●类的设计 01.类和对象的概念 类和对象是面向对象编程的两个核心...

  • python语法入门五

    类和对象 类和对象 基础 继承:python为多继承 类、类对象和实例对象 当实例对象声明后,再删除类对象,那么该...

  • 13.Python类和对象

    目标 类和对象的概念 类和对象的关系 类的设计 01. 类和对象的概念 类 和 对象 是 面向对象编程的 两个 核...

  • 12.Python类和对象

    目标 类和对象的概念 类和对象的关系 类的设计 01. 类和对象的概念 类 和 对象 是 面向对象编程的 两个 核...

  • 类和对象 ​​​

  • 类和对象

    对象=属性+方法 self 由同一个类可以生成无数对象,当一个对象的方法被调用是,对象会将自身的引用作为第一个参数...

网友评论

      本文标题:python10 类和对象

      本文链接:https://www.haomeiwen.com/subject/smuomhtx.html