美文网首页IT狗工作室
第6篇:Cython的面向对象编程(中篇)

第6篇:Cython的面向对象编程(中篇)

作者: 铁甲万能狗 | 来源:发表于2020-04-21 22:21 被阅读0次

我们在前一篇已经说过Python版本实现的类和Cython版本的类的区别,其中一个最为显著的特征是Python类实例的属性数据存放一个内部字典中即__ dict__,我们了解dict的底层是基于哈系表

例如 Fruit的实例下,如下图查看所有实例属性的数据

ss8.png
另外我在前面的随笔说过,纯Python版本的面向对象编程中,不存在封装一说,因为Python的类是基于解析语言构建,Python运行时系统并没有像C++/JAVA提供对类实例的属性/方法的访问控制

我们先来查看原生Python定义的Fruit类,我们可以通电点号访问符实访问Fruit实例的属性,同时可以修改其属性


因此Python定义的类默认所有属性是公开,并且可修改的,甚至Python运行时还允许我们动态添加新的类属性变量,如下操作,动态添加weight属性

Python类性能问题

上面的例子,其实就突出一点Python类强调运行时的动态性,因为Python类的实例属性存储内部dict中,而dict的本质就是哈系表,但纯Python类实例的属性数量规模不宜过大,因为哈系表元素(类实例属性的引用)的数量超过负载系数,会导致字典重散列,在典型的哈希表的内存模型中,重散列(Rehashing)意味着

  1. 带来巨大的内存消耗,因为重散列意味着,运行时频繁添加或删除类实例属性,可能导致已分配内存利用率低下
  2. 字典内部若类实例属性存在散列冲突,即访问或修改某些实例属性的效率时间复杂度可能为O(n)

扩展阅读:如果你对哈希表基本原理不熟悉,可以阅读我之前写的随笔《C++哈希表-负载系数与重散列》,那篇是非收费文章..

Cython类的访问控制

接下来,我们讨论Cython版本的类Fruit,这是一个纯Cython的扩展类,位于一个cy_fruit.pyx的文件中

#cython:language_level=3

cdef class Fruit(object):
    '''Fruit Type'''
    
    cdef str name
    cdef double qty
    cdef double price
    
    def __init__(self,nm,qt,pc):
          self.name=nm
          self.qty=qt
          self.price=pc

    def amount(self):
          return  self.qty*self.price

下面是一个错误示例的演示



当我们尝试对一个C实现的扩展类的实例调用一个类似Python类的内部字典属性__ dict__会发生报错,会提示 no attribute '__ dict __'错误,


ss8.png
由于Cython关键字 cdef class就是告知Cython编译器将Fruit类的定义编译为C版本的类Fruit,若你了解C的话,C版本的Fruit类定义可以类比下面的C代码,
typedef struct{
    char* name;
    double qty;
    double price;
    
}    Fruit;

double amount(Fruit* self){
      return self->qty*self->price;
}

没错,cdef class 在底层就做了这些底层的操作:

  1. 对于C来说,Fruit类的本体就是一个具备以上字段的结构体,
  2. Fruit类在实例化时,必须明确告知编译器它自己内部字段(属性)的类型,编译器根据字段的类型能计算出整个Fruit结构体实例化时该为它分配多大的内存量。

当然上面不是完全的描述,我们在通过例子去进一步分析cdef关键字的对Cython类的操作。

反例演示:当我们尝试通过点号访问符访问C级别的Fruit类实例属性,哦~!一一报错,这又是何解呢?你可以自行思考一下。


此时,你应该想到Cython的关键字cdef class集成了C++ class的特性就是类成员访问控制,C++的关键字class就是提供了访问控制的struct的加强版。这里需要说一下:Cython与C++访问控制修饰符的对应关系。
  • private:对于Cython编译器来说,任何使用cdef定义的类属性/方法默认是私有的,类外部代码无法访问之,并且在声明类成员时,Cython语法层面不提供显式的private关键字声明,因为像cdef private double price 等同画蛇舔足。
  • public: Cython编译器继承了C++这一特性,例如类内声明cdef public double price,表示外部代码可以自由访问和修改该属性值。
  • protected:要在Cython中实现类似C++类继承的protected访问控制特性,在Cython中不能使用protected,而是使用cppclass关键字,关于此方面内容以后再说。

再多说一句,我们知道C的struct是简单的聚合类型,也就是对基本数据类型聚合扩展新的用户自定义类型而已,且不提供任何访问限制。而Python 的C底层的API实现中使用最为频繁的函数参数就是struct PyObject*,只要Python解析器在运行时解析任何动态变量都会首先指向PyObject这个C版本的结构体指针。这恰好说明Python运行时系统对类实例属性没有访问控制的根本原因。

Ok,我们通过一些例子加深并巩固上面的概念,请看下面添加访问控制修饰符后的Cython类

#cython:language_level=3

cdef class Fruit(object):
    '''Fruit Type'''
    
    cdef readonly str name
    cdef public double qty
    cdef readonly double price
    
    def __init__(self,nm,qt,pc):
          self.name=nm
          self.qty=qt
          self.price=pc

    cdef public double amount(self):
          return  self.qty*self.price

下面的调用Cython版本的Fruit类,类实例属性name和类实例属性qty都能被外部的Python代码调用,如下图,因为readonly和public允许外部Python代码访问其类属性

  • 属性namereadonly关键字
  • 属性qty被public关键字修饰
  • 属性price被readonly关键修饰

值得一提的是,当readonly关键字修饰类属性时,其实很想Java中的final关键字的原理一样:类实例属性值一旦在初始化之后便不能更改,但允许调用代码访问。我们可以通过下面示例来演示。

public关键字允许外部Python代码调用被public修饰的类实例属性,并且可以自由修改类实例属性的值

更新中.....

相关文章

  • 第6篇:Cython的面向对象编程(中篇)

    我们在前一篇已经说过Python版本实现的类和Cython版本的类的区别,其中一个最为显著的特征是Python类实...

  • Python和其它27种编程语言

    27 种语言 过程型编程语言: C, Rust, Cython 面向对象数据建模语言: Java, C#, Eif...

  • “老奶奶”的python学习笔记(12)

    知识体系 第12关:面向对象编程 知识点 面向对象编程(Object Oriented Programming) ...

  • 第6篇:Cython的面向对象编程(前篇)

    在Python中,一切都是对象。 具体来说是什么意思? 在最基本的层面上,一个对象具有三样东西 标识(id):对象...

  • JS设计模式 -- 面向对象 -- 1 封装

    以下内容来自张荣铭《JavaScript设计模式》第2章。 两种编程风格 -- 面向过程与面向对象。 面向对象编程...

  • 面向对象基础

    面向对象编程包括: 面向对象的分析(OOA) 面向对象的设计(OOD) 面向对象的编程实现(OOP) 面向对象思想...

  • 面向对象_初识

    目录 面向对象编程介绍 类与对象介绍 私有属性与私有方法 面向对象编程 1. 面向对象编程介绍 面向对象编程:Ob...

  • PHP全栈学习笔记8

    面向对象的基本概念,面向对象编程,oop,面向对象,面向对象的分析,面向对象的设计,面向对象的编程,什么是类。 类...

  • PHP全栈学习笔记8

    面向对象的基本概念,面向对象编程,oop,面向对象,面向对象的分析,面向对象的设计,面向对象的编程,什么是类。 类...

  • 谈谈面向对象编程

    何为面向对象编程 面向对象编程简介 面向对象编程(Object-oriented Programming,缩写:O...

网友评论

    本文标题:第6篇:Cython的面向对象编程(中篇)

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