您的位置:首页 > 编程语言 > Python开发

类与对象学习笔记(Python)

2016-10-15 16:19 411 查看
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)
另外,在函数中,p是blank的一个别名,如果函数修改了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.

    """

文档字符串列出了属性:width和height是数字;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)可以通过对一个对象的某个属性赋值来修改它的状态,例如:要修改一个矩形的尺寸而保持它的位置不变,可以修改属性的width和height的值:
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
在函数中,rect是box的别名,所以如果函数修改了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操作符判断出p1和p2不是同一个对象,==操作符的默认行为和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']

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: