类与对象学习笔记(Python)

1、 用户定义类型

1)用户定义的类型也称为(class),类的定义形式如下:

class Point(object):

   """Represents a point in 2-D space."""

定义头表示新的类是一个Point,它是object的一种,而object是一个内置函数。

2)定义一个叫做Point的类会创建一个类对象。

In [7]:print Point

<class '__main__.Point'>

 

  因为Point是在程序顶层定义的,它的“全名”是__main__.Point

3)类对象像一个创建对象的工厂。要新建一个Point对象,可以把Point当作函数来调用。

In [9]: blank=Point()

In [10]: print blank

<__main__.Pointobject at 0x000000000A121320>

返回值是到一个Point对象的引用,我们将它赋值给变量blank。新建一个对象的过程称为实例化(instantiation,而对象是这个类的一个实例

当打印一个实例时,Python会告诉你它所属的类型,以及存储在内存中的位置,前缀0x表示后面的数字是16进制的。

 

2、属性

(1)      可以使用句点给实例赋值

In [21]: blank.x=3

In [22]: blank.y=4

注:x,y可以在类定义中不必事先定义

我们是将值赋值给一个对象的有命名的元素。这些元素称为属性(attribute

变量blank引用向一个Point对象,它包含两个属性。每个属性引用一个浮点数。可以使用相同的语法来读取一个属性的值。

In [26]: blank.x

Out[26]: 3

In [27]: blank.y

Out[27]: 4

(2) 可以在任意表达式中使用句点表示法。例如:

In [29]: print '(%g, %g)' %(blank.x, blank.y)

(3, 4)

In [30]: import math

In [31]: distance=math.sqrt(blank.x**2+blank.y**2)

In [32]: print distance

5.0

3)可以将一个实例作为实参按照通常的方式传递

In [33]: def print_point(p):   

        """除‘%f’外,还可以用‘%e’、‘%g’表示浮点数,‘%e’用指数形式输出,‘%g’根据实际情况输出,默认情况下最多保留6位有效数字。"""

    ...: print '(%g,%g)'%(p.x,p.y)

    ...:

In [34]: print_point(blank)

(3,4)

另外,在函数中,pblank的一个别名,如果函数修改了p,则blank也会改变,如下:

In [35]: def print_point(p):

    ...: print '(%g,%g)'%(p.x,p.y)

    ...: p.x=20

    ...:

In [36]: print_point(blank)

(3,4)

In [37]: blank.x

Out[37]: 20

(3) 补充(查看类的定义信息)

In [38]: help(Point)

Help on class Point in module __main__:

 

class Point(__builtin__.object)

| Represents a point in 2-D space.

|

| Data descriptors defined here:

|

| __dict__

| dictionary for instance variables (if defined)

|

| __weakref__

| list of weak references to theobject (if defined)

 

3、举例:设计一个表达矩形的类

有时候对象应该有哪些属性非常明显,有时候要根据需求做决定。

1)定义一个类:

class Rectangle(object):
    """Represents a rectangle. 
 
    attributes: width, height, corner.
    """

文档字符串列出了属性:widthheight是数字;corner是一个Point对象,用来指定左下角的顶点。

2)要表达一个矩形,你需要实例化一个Rectangle对象,并对其属性赋值:

In [39]: class Rectangle(object):

    ...: """Represents a rectangle.

    ...:

    ...: attributes: width, height, corner.

    ...: """

    ...:

In [40]: box=Rectangle()

In [41]: box.width=100

In [42]: box.height=200

In [43]: box.corner=Point()

In [44]: box.corner.x=0

In [45]: box.corner.y=0

 表达式box.corner.x表示:去往box引用的对象,并选择属性corner,接着去往那个对象,并选择属性x.

 

4、作为返回值的实例

新建一个对象的过程称为实例化(instantiation,而对象是这个类的一个实例

函数可以返回实例,例如:

In[48]: def find_center(rect):

    ...: p=Point()

    ...: p.x=rect.corner.x+rect.width/2.0

    ...: p.y=rect.corner.y+rect.height/2.0

    ...: return p

    ...:

函数可以返回实例。Find_center接收Rectangle对象作为参数,并返回一个point对象,包含这个Rectangle的中心点的坐标。例如:

In [49]: center=find_center(box)

In [50]: center.x

Out[50]: 50.0

In [51]: center.y

Out[51]: 100.0

In [54]: print_point(center)

(50,100)

 

5、对象是可变的

1)可以通过对一个对象的某个属性赋值来修改它的状态,例如:要修改一个矩形的尺寸而保持它的位置不变,可以修改属性的widthheight的值:

In [55]: box.width=box.width+50

In [56]: box.height=box.height+100

2)也可以编写函数来修改对象,例如:

In [61]: def grow_rectangle(rect, dwidth, dheight):

    ...: rect.width=rect.width+dwidth

    ...: rect.height=rect.height+dheight

    ...:

In [62]: grow_rectangle(box,50,0)

In [63]: box.width

Out[63]: 250

In [64]: box.height

Out[64]: 300

In [65]: grow_rectangle(box,50,0)

 

In [66]: box.width

Out[66]: 300

In [67]: box.height

Out[67]: 300

在函数中,rectbox的别名,所以如果函数修改了rect,则box也改变了。

 

6、复制

1)别名的使用有时候会让程序更难阅读,因为一个地方的修改可能会给其他地方带来意想不到的变化,要跟踪掌握所有引用到一个给定的对象的变量非常困难。

In [71]: box.width

Out[71]: 300

In [72]: box.height

Out[72]: 300

In [73]: box1=box

In [74]: box1.width

Out[74]: 300

In [75]: box1.height

Out[75]: 300

In [76]: box1.width=123

In [77]: box.width

Out[77]: 123

2)浅复制

使用别名的替代方案是复制。copy模块里有一个函数copy可以复制任何对象:

In [78]: p1=Point()

In [79]: p1.x=3.0

In [80]: p1.y=4.0

In [81]: import copy

In [82]: p2=copy.copy(p1)

In [83]: print_point(p1)

(3,4)

In [84]: print_point(p2)

(3,4)

In [85]: p1 is p2

Out[85]: False

In [86]: p1==p2

Out[86]: False

is操作符判断出p1p2不是同一个对象,==操作符的默认行为和is的操作符相同,它会检查唯一性,而不是对象的相等性。

如果使用copy.copy复制一个Retangle,你会发现它复制了Rectangle对象,但并不复制内嵌的Point对象。这种行为即混乱不清,又容易导致错误

In [89]: box2=copy.copy(box)

In [90]: box2 is box

Out[90]: False

In [91]: box2.corner is box.corner

Out[91]: True

(4) 深复制(deep copy)推荐

针对copy.copy引起的问题,copy模块还提供了deepcopy方法,它不但复制对象,还复制对象中引用的对象,甚至他们引用的对象,依次类推。

In[92]: box3=copy.deepcopy(box)

In[93]: box3.corner is box.corner

Out[93]: False

 

7、调试

操作对象时,可能会遇到一些异常。如果访问一个不存在的对象,会得到AttributeError:

In [99]: p=Point()

In [100]: p.z

Traceback(most recent calllast):

File"<ipython-input-100-6dce4e43e15c>", line1,in<module>

p.z

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

(1) 如何不清除一个对象是什么类型,可以使用type

In [101]: type(p)

Out[101]: __main__.Point

(2) 不确定一个对象是否拥有某个特定属性,使用内置函数hasattr(has attr)查看:

In [102]: p.x=10

In [103]: hasattr(p,'x')

Out[103]: True

In [104]: hasattr(p,'y')

Out[104]: False

第一个形参可以是任何对象,第二个形参是一个字符串,包含属性的名称。

(3) 查看对象所有的属性dir

In[105]: dir(box)

Out[105]:

['__class__',

'__delattr__',

'__dict__',

'__doc__',

'__format__',

'__getattribute__',

'__hash__',

'__init__',

'__module__',

'__new__',

'__reduce__',

'__reduce_ex__',

'__repr__',

'__setattr__',

'__sizeof__',

'__slotnames__',

'__str__',

'__subclasshook__',

'__weakref__',

'corner',

'height',

'width']

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值