Python的面向对象

栏目: 后端 · 前端 · 发布时间: 8年前

内容简介:Python的面向对象

1. 进入 Python 的面向对象

python 作为一个弱类型的动态语言,其面向对象的方式与 Java 、C++这种强类型的语言相比还是有很大的不同的。其中Java、C++如何此处不作赘述。

首先,先预设这么一个类:

# code-01
class Person(object):
    def __init__(self, name):
        self.name = name
    def setName(self, name):
        self.name = name
    def getName(self):
        return self.name

像这样定义属性:

# code-02
    def __init__(self, name):
        self.name = name    # self.name 代表的就是定义的属性(先声明再定义?还是直接定义?由你决定!)

像这样定义函数:

# code-03
    def setName(self, name):        # 这里的setName()、getName()函数都可以通过实例来调用,self代表的是实例本身,
                                    # 其他函数的参数问题不在本文讨论之列,另外:注释不要像我这么写
        self.name = name
    def getName(self):
        return self.name

2. 访问控制

python 的访问控制干脆直接,属性 权限 从属性的 名字 上即可得到。

此处按照常规的访问权限解释:

  • public

code-01 的代码所示:

python # code-04 def __init__(self, name = '') self.name = name

这里的 self.name 就是 public 的,我们可以通过下面这种方式访问这个属性:

python # code-05 if __name__ == '__main__': p = Person("Marry") print(p.name) # 这里会输出: Marry

同样的,这里的 setName()getName() 也是 public 的,我们也可以通过下面这种方式来访问:

python # code-06 if __name__ == '__main__': p = Person("Marry") print(p.getName()) # 这里会输出: Marry

  • private

这里我们把上面 code-01 的代码修改 __init__(self,name) 函数,如下所示:

python # code-07 class Person(object): def __init__(self, name = "",marry = False): self.name = name self.__marry = marry

并添加如下代码,其他部分不变。

python # code-08 class Person(object): def __isMarry(self): return self.__marry

__isMarry(self) 这样的函数就是 private 函数, self.__marry 这样的属性(变量)就是 private 属性。

那么,如果再直接访问它的话,就会报错:

```python

# code-09

if name == ' main ':

p = Person("Marry")

print(p.getName()) # 这里会输出: Marry

print(p.__isMarry()) # 这里会报错

Traceback (most recent call last):

File "/media/somote/新加卷/pytest/ootest.py", line 16, in

  • protected

事实上,python 并不提供这个权限,所以在此不作描述。

3. 内置装饰器

@property

先说一下property()函数,这里有必要提一下类的三个内置函数:setattr、getattr(以及getattribute)、delattr,关于关于这三个函数该如何使用,请自行搜索

property()的作用就在于把 setattrgetattrdelattr 三个函数给统一起来,如下所示:

# code-10
class Girl (Person):
    """
    我们新增一个 Girl 类,继承自 Person,同时我们为它新增一些身材属性 bust、waist、hip
    """

    def __init__(self, name):
        super(Girl, self).__init__(name)
        self.bust = 80
        self.waist = 80
        self.hip = 80
    # 这里的 figure 参数实际上就是*args(tuple类型)
    def setfigure(self, figure):
        self.bust, self.waist, self.hip = figure

    def getfigure(self):
        return self.bust, self.waist, self.hip

    def delfigure(self):
        del self.bust
        del self.waist
        del self.hip
    # 这里是重点
    figure = property(getfigure, setfigure, delfigure)

运行:

# code-11
if __name__ == '__main__':
    g = Girl("Jane")
    print(g.name)
    g.setfigure((50,60,90))     # 通过函数来设置
    print(g.getfigure())# 50,60,90
    '''
    通过figure属性,绑定到其property()函数的 setter、getter、deller函数上,注意:这里必须把参数给齐,否则会报错
    '''
    g.figure = 60,90,90         
    print(g.figure)     # 60,90,90
    print(g.bust)   # 60
    print(g.waist)  # 90
    print(g.hip)    # 90

我们也可以通过 @property 来设置属性:

# code-12
class Girl (Person):
    """
    我们新增一个 Girl 类,继承自 Person,同时我们为它新增一些身材属性 bust、waist、hip
    """
    def __init__(self, name):
        super(Girl, self).__init__(name)
        self.bust = 80
        self.waist = 80
        self.hip = 80

    # 这里预先把 figure() 装饰為 figure属性,所以可以在下面设置 setter、deleter,注意: getter 由这里的figure()代替了
    @property
    def figure(self):
        print("get value")
        return self.bust, self.waist, self.hip
    
    @figure.setter
    def figure(self, figure):
        print("set value")
        self.bust, self.waist, self.hip = figure

    @figure.deleter
    def figure(self):
        del self.bust
        del self.waist
        del self.hip

运行:

# code-13
if __name__ == '__main__':
    g = Girl("Jane")
    print(g.name)           # Jane
    g.figure = 60,90,90     # set value
    print(g.figure)         # get value
                            # 60,90,90
    print(g.bust)   # 60
    print(g.waist)  # 90
    print(g.hip)    # 90

通过 property()@property 这种方式,可以控制某些属性的读写权限

@staticmethod

顾名思义, staticmethod 就是静态方法的意思,那么首先先来了解一下静态属性,在 code-12 的代码里,我们作如下修改:

# code-14
class Girl (Person):
    girlsnum = 0
    # primary code here

运行:

# code-15
if __name__ == '__main__':
    g = Girl("Jane")
    print(g.girlsnum)       # 1
    g1 = Girl("Marry")
    print(g.girlsnum)       # 2
    g2 = Girl("Lucy")
    print(g1.girlsnum)      # 3
    print(Girl.girlsnum)    # 3

可以看出, girlsnum 这个属性就是一个静态的类属性,那么 staticmethod 呢?

我们在 code-12 的基础上再次添加一些内容:

# code-16
class Girl (Person):
    # primary code here
    @staticmethod
    def info(name="", figure=()):
        return "Name : " + name + " \tFigure : " + str(figure)

然后运行:

# code-17
if __name__ == '__main__':
    g = Girl("Jane")
    print(Girl.info("Jane", g.figure))      # Name : Jane     Figure : (80, 80, 80)

或许,你灵机一动把 info(name="", figure=()) 改为 info(self,name="", figure=()) ,那么去看看会发生什么吧![^1]

@classmethod

其实 @classmethod@staticmethod 很难说到底有什么不同,水平有限,其具体用途留待探讨,此处只作简要说明。我们在 code-12 的基础上作如下修改:

# code-18
class Girl (Person):
    # primary code here
    @classmethod
    def build(clazz):
        print("ClassMethod")

运行:

# code-19
if __name__ == '__main__':
    g = Girl("Jane")
    Girl.build()        # ClassMethod

注意:

  1. @classmethod 所装饰的函数,最少需要一个参数,并且这个参数就是当前类本身
  2. 就调用而言, instancemethod_要宽泛于_staticmethod_和_classmethod (实例可以调用静态方法或者类方法,反之不可)

4. 某些属性

__dict__

__dict__ 主要保存的是实例的属性键值对,我们对 code-12 的代码作如下修改并运行:

# code-20
if __name__ == '__main__':
    g = Girl("Jane")
    print(g.__dict__)   # {'hip': 80, 'name': 'Jane', 'bust': 80, 'waist': 80}

注意: @property 所装饰的 figure 并没有作为属性被打印出来

__slots__

我们对 code-12 的代码作如下修改:

# code-07
class Girl (Person):
    __slots__ = ("bust", "waist", "hip")
    # primary code here

此时,Girl类应当只有三个属性: bustwaisthip 了,但是事实并非如此,我们运行如下代码:

# code-21
if __name__ == '__main__':
    g = Girl("Jane")
    g.age = 25

发现仍能通过,并且通过 dir(g) 可以查看到age属性,为什么呢?

原因在于: Girl 的基类 Person 并没有用 __slots__ 来限制属性,也就是说 __slots__ 的作用范围仅仅包括当前类,所以:

# code-22
class Person(object):
    __slots__ = ("name")
    # primary code here

此时,再次运行 code-21 就会发现解释器会报错


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

High Performance Python

High Performance Python

Andrew Lewis / O'Reilly Media, Inc. / 2010-09-15 / USD 34.99

Chapter 1. Introduction Section 1.1. The High Performance Buzz-word Chapter 2. The Theory of Computation Section 2.1. Introduction Section 2.2. Problems Section 2.3. Models of Computati......一起来看看 《High Performance Python》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具