Python 类(十一)

首先申明下,本文为笔者学习《Python学习手册》的笔记,并加入笔者自己的理解和归纳总结。

1. 类的定义

class语句创建类对象并将其赋值给变量名,类可以看成是模块中的变量。

>>> class Sample:
    def setValue(self, val):          # self指向类实例
        self.val = val                # 添加一个实例变量val
    def getValue(self):               # 返回实例变量val的值
        return self.val

2. 创建实例

每个实例都拥有自己的命名空间,实例变量的修改不会影响其他实例。

>>> s = Sample()                      # 在Sample加上括号创建类实例
>>> s.setValue("Hello World!")        # 调用方法setValue
>>> s.getValue()
'Hello World!'

>>> s1 = Sample()                     # 创建另一个实例s1
>>> s1.setValue("Welcome")            # 在s1上调用方法
>>> s1.getValue()
'Welcome'

>>> s.getValue()                      # s和s1互不干扰
'Hello World!'

3. 访问变量和方法

通过逗号(.)访问变量和方法

>>> s = Sample()
>>> s.val = "Welcome"                 # 访问实例变量
>>> s.getValue()
'Welcome'

通过__dict__变量访问变量

>>> s.__dict__                        # __dict__是一个字典
{'val': 'Welcome'}

>>> s.__dict__.get("val")
'Welcome'

通过类来访问方法

>>> Sample.setValue(s, "value init")  # 类似于s.setValue("value init")
>>> s.getValue()
'value init'

4. 构造函数

新的实例构造时,会调用__init__()方法。

>>> class Shape:
    def __init__(self, x, y, w=10, h=10):
        self.x = x
        self.y = y
        self.width = w
        self.height = h
    def draw(self):
        print "draw"

访问构造函数,构造函数同一般的函数一样,可以设默认值,通过关键字访问。

>>> s = Shape(4, 5)                 # width和height采用默认值
>>> s.__dict__
{'y': 5, 'x': 4, 'height': 10, 'width': 10}

>>> s = Shape(4, 5, 100)
>>> s.__dict__
{'y': 5, 'x': 4, 'height': 10, 'width': 100}

>>> s = Shape(4, 5, w=50, h=45)     # 采用混合参数
>>> s.__dict__
{'y': 5, 'x': 4, 'height': 45, 'width': 50}

对于一个已经定义了构造函数的类来说,默认构造方法不一定有效。

>>> s = Shape()
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    s = Shape()
TypeError: __init__() takes at least 3 arguments (1 given)

5. 类属性

__dict__显示类的属性。

>>> s = Shape(4, 5, 50, 45)
>>> s.__dict__
{'y': 5, 'x': 4, 'height': 45, 'width': 50}

>>> Shape.__dict__                  # 类显示属性和方法
{'__module__': '__main__', 'draw': <function draw at 0x0000000002BF1208>, '__ini
t__': <function __init__ at 0x0000000002BF1198>, '__doc__': None}

__bases__显示父类

>>> Shape.__bases__
()

>>> class Circle(Shape):            # Cirle继承Shape类
    pass
>>> Circle.__bases__
(<class __main__.Shape at 0x0000000002BED708>,)

>>> class Oval(Shape, Circle):      # Oval继承两个类
    pass
>>> Oval.__bases__
(<class __main__.Shape at 0x0000000002BED708>, <class __main__.Circle at 0x0000000002BED768>)

6. 类变量

Shape中有一个变量color,作为Shape的类变量。

>>> Shape.color = "red"
>>> s1 = Shape(3, 4)                # 创建Shape实例s1
>>> s2 = Shape(5, 6)                # 创建Shape实例s2
>>> Shape.color, s1.color, s2.color # 所有实例的color都是一样的
('red', 'red', 'red')

修改这个类变量,会影响其他实例。

>>> Shape.color = "blue"            # 修改类变量后,所有的实例都被修改
>>> Shape.color, s1.color, s2.color
('blue', 'blue', 'blue')

如果在某个实例中修改了这个变量,实际会把这个变量本地化,二期不会影响其他实例。

>>> s1.color = "green"              # 实例设置color值,color成为实例的本地变量
>>> Shape.color, s1.color, s2.color
('blue', 'green', 'blue')

>>> Shape.color = "red"             # 再次修改Shape类的color变量
>>> Shape.color, s1.color, s2.color # s1已经设置了本地变量,不会受到影响
('red', 'green', 'red')

可以设置方法。

>>> def draw(self):
    print "position at (%d, %d)" % (self.x, self.y)
>>> Shape.draw = draw               # 把方法赋值给一个变量
>>> Shape.draw(s1)
position at (3, 4)                  # Shape类调用方法

>>> s1.draw()                       # s1实例调用方法
position at (3, 4)

7. 方法重载

两个相同名称的方法,最后出现的方法会覆盖之前所有的方法,类似于给一个变量赋值,只有最后一次有效

>>> class Sample:
    def add(self, val1, val2):
        return val1 + val2
    def add(self, val1, val2, val3):
        return val1 + val2 + val3

>>> s = Sample()
>>> s.add(13, 23)                   # 调用add方法,add方法被覆盖
Traceback (most recent call last):
  File "<pyshell#71>", line 1, in <module>
    s.add(13, 23)
TypeError: add() takes exactly 4 arguments (3 given)

>>> s.add(13, 23, 37)
73

8. 类的继承

8.1 继承

实现继承需要在类名后面的括号内加入需要继承的类,Circle类继承了Shape类,同时继承了变量、构造函数和其他方法。

>>> class Shape:
    def __init__(self, x, y, w=10, h=10):		
        self.x = x
        self.y = y
        self.width = w
        self.height = h
    def draw(self):
        print "Shape draw"

>>> class Circle(Shape):
    pass

调用Circle

>>> c = Circle(50, 65)               # Circle继承了Shape的构造函数和属性
>>> c.__dict__
{'y': 65, 'x': 50, 'height': 10, 'width': 10}

>>> c.draw()                         # Circle继承了Shape的draw方法
Shape draw

8.2 方法覆盖。

覆盖Circle的构造函数和draw方法。

>>> class Circle(Shape):
    def __init__(self, x, y, radius=10):
        Shape.__init__(self, x, y, 0, 0)
        self.radius = radius
    def draw(self):
        print "Circle draw"

>>> c = Circle(50, 65)               # 调用Circle的构造函数
>>> c.__dict__
{'y': 65, 'x': 50, 'height': 0, 'radius': 10, 'width': 0}

>>> c = Circle(50, 65, 20)
>>> c.__dict__
{'y': 65, 'x': 50, 'height': 0, 'radius': 20, 'width': 0}

>>> c = Circle(50, 65, 20, 20)
Traceback (most recent call last):
  File "<pyshell#188>", line 1, in <module>
    c = Circle(50, 65, 20, 20)
TypeError: __init__() takes at most 4 arguments (5 given)

>>> c.draw()                         # 调用Shape的draw方法
Circle draw

8.3 方法调用顺序

Sampe有两个父类Sup1Sup2。查找顺序Sample->Sup1->Sup2
Sup1Sup2是根据在Sample继承顺序排列的。

>>> class Sup1:
    def fun(self):
        print "Sup1.fun"
    def fun1(self):
        print "Sup1.fun1"

>>> class Sup2:
    def fun(self):
        print "Sup2.fun"
    def fun1(self):
        print "Sup2.fun1"
    def fun2(self):
        print "Sup2.fun2"

>>> class Sample(Sup1, Sup2):
    def fun(self):
        print "Sample.fun"

>>> s = Sample()
>>> s.fun()                          # 调用Sample自身的fun方法
Sample.fun

>>> s.fun1()                         # 调用Sup1的fun1方法
Sup1.fun1

>>> s.fun2()                         # 调用Sup2的fun2方法
Sup2.fun2

9. 抽象类

>>> from abc import ABCMeta, abstractmethod
>>> class Super:
    __metaclass__ = ABCMeta          # metaclass设置为ABCMeta
    @abstractmethod                  # 方法添加abstractmethod
    def fun(self):
        pass

>>> Super()
Traceback (most recent call last):
  File "<pyshell#46>", line 1, in <module>
    Super()
TypeError: Can't instantiate abstract class Super with abstract methods fun

>>> class Sample(Super):
    def fun(self):
        print "in sample"
>>> Sample().fun()
in sample

10. 特殊变量

>>> class Sample:
    def __init__(self):
        self._x = 12
        self.__x = 13
    def fun(self):
        print "fun"
    def _fun(self):
        print "_fun"
    def __fun(self):
        print "__fun"

>>> s = Sample()
>>> dir(s)                           # __x和__fun变成_Sample__xx
['_Sample__fun', '_Sample__x', '__doc__', '__init__', '__module__', '_fun', '_x', 'fun']

11. 限定属性__slots__

>>> class Sample(object):            # 定义一个继承object的类
    __slots__ = ("name", "age")      # __slots__定义了两个属性

>>> s = Sample()
>>> s.name = "Mike"                  # 可以进行属性name
>>> s.name
'Mike'

>>> s.addr = "ShangHai"              # addr没有定义,无法访问
Traceback (most recent call last):
  File "<pyshell#216>", line 1, in <module>
    s.addr = "ShangHai"
AttributeError: 'Sample' object has no attribute 'addr'

12. 自定义类的打印信息

class实例会调用默认打印信息。

>>> class Sample:
    pass
>>> Sample()
<__main__.Sample instance at 0x03302940>

字符串表达式__repr__定义交互式界面的输出。

>>> class Sample:
    def __repr__(self):
        return "[Sample, repr]"

>>> Sample()                        # 交互式界面调用repr方法
[Sample, repr]

>>> print Sample()                  # print方法也会调用repr方法
[Sample, repr]

字符串表达式__str__定义print的输出。

>>> class Sample:
    def __str__(self):
        return "[Sample, str]"

>>> Sample()                        # 交互式界面调用默认方法
<__main__.Sample instance at 0x0000000002AC8848>

>>> print Sample()                  # print方法调用str方法
[Sample, str]

__repr____str__都被定义。

>>> class Sample:
    def __repr__(self):
        return "[Sample, repr]"
    def __str__(self):
        return "[Sample, str]"

>>> Sample()                        # 交互式界面调用repr方法
[Sample, repr]

>>> print Sample()                  # print方法调用str方法
[Sample, str]

相关文章
Python 数字类型(一)
Python 布尔型(二)
Python 字符串(三)
Python 列表(四)
Python 字典(五)
Python 元组(六)
Python 集合(七)
Python 变量和作用域(八)
Python 语句(九)
Python 函数(十)
Python 类(十一)
Python 模块(十二)
Python 文档(十三)
Python 文件(十四)
Python 异常(十五)
Python 运算符重载(十六)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值