特殊成员

一、特殊成员补充:

  • 索引、切片
    • 当对象后面加小括号,自动执行call方法
    • 当对象后面加中括号,会自动执行 item相关方法
      1. __getitem__(self,item)
      2. __setitem__(self, key, value)
      3. __delitem__(self, key)
  • 调用方式:
    • [item ] 索引:
      • 以“索引”方式进行方法调用,中括号中的item被当做一个str 类型
class Class1:

def __getitem__(self, item):

print(‘getitem , get:{}, type:{}‘.format(item, type(item)))

def __setitem__(self, key, value):

print(‘setitem , key:{}  value:{},  type:{},type:{}‘.format(key, value, type(key), type(value)))

def __delitem__(self, key):

print(‘delitem,  key:{}, type:{}‘.format(key, type(key)))

# 实例化并调用

obj = Class1()

obj[‘test1‘]                 #“对象索引”,自动触发执行__getitem__()方法

obj[‘test2‘] = ‘value2‘ #“对象索引”赋值,自动触发执行__setitem(key,value) 方法,并将索引的key和值value传给形参

del obj[‘test3‘]           #    删除“对象索引”,自动触发执行 __delitem__(self,key) 方法,并自动将索引的key传递给形参

    • [star:stop:step] 切片
      • 以“切片”方式进行方法调用,中括号中的内容被当做一个slice对象,并将start,stop,step传递给slice的3个字段,slice.start ,slice.stop,slice.step
class Class1:

def __getitem__(self, item):

print(item, type(item))

print(‘item start:{}‘.format(item.start))

print(‘item stop:{}‘.format(item.stop))

print(‘item step:{}‘.format(item.step))

def __setitem__(self, key, value):

print(key, type(key), value, type(value))

print(‘key start:{}‘.format(key.start))

print(‘key stop:{}‘.format(key.stop))

print(‘key step:{}‘.format(key.step))

print(‘value:{}‘.format(value))

def __delitem__(self, key):

print(key, type(key))

print(‘key start:{}‘.format(key.start))

print(‘key stop:{}‘.format(key.stop))

print(‘key step:{}‘.format(key.step))

# 实例化并执行

obj = Class1()

obj[1:2:3]  # 对象切片,会自动执行__getitem__(self, item) 函数,并将[start:stop,step] 传递给 slice 对象

obj[1:2:3] = [1, 2, 3, 4, 5] # 切片赋值,会自动执行__setitem__(slef,key,value) 函数,并将 [start:stop,step] 传递给 slice 对象 key; 值赋给 value

del obj[1:2:3]  # 切片删除,会自动执行__delitem__(self, key) 函数,并将[start:stop,step] 传递给 slice 对象

    • 有序字典:
      • 字典没有提供有序的功能,需要在字典类的基础上进行操作
      • 实际是字典的key有序,即将key放在列表中
    class Mydic(dict):

    def __init__(self):

    self.lst = []

    super(Mydic, self).__init__()

    def __setitem__(self, key, value):

    self.lst.append(key)

    super(Mydic, self).__setitem__(key, value)

    def __str__(self):

    temp_lst = []

    for x in self.lst:

    dic_value = super(Mydic, self).get(x)

    temp_lst.append(‘{}:{}‘.format(x, dic_value))

    f_dic = ‘{‘ + ‘,‘.join(temp_lst) + ‘}‘

    return f_dic   # __str__ 方法 return什么值,就输出什么值

    # 实例化并调用

    obj = Mydict()

    obj[‘k1‘] = 123

    obj[‘k2‘] = 456

    obj[‘k3‘] = 789

    obj[‘k4‘] = ‘abc’

    print(obj)   # 调用__str__ 方法,此时每次输出的都是有序字典

  • 迭代方法:
    • __iter__()   //一个方法要想能被迭代,就要实现这个方法,且该方法返回一个迭代对象
      • 可迭代对象:
        • 一个实现了“迭代协议”的对象,迭代协议如下:
          • __iter__() :返回iterator对象本身
          • __next__(): 每当该函数被调用,返回(return)一个值,并直到StopIteration 异常时停止
      • python 的 for 循环遍历过程:
        1. 先调用__iter__()方法,来获得迭代器
        2. 调用迭代器的 next()方法,获得数据,直到抛出StopIteration异常
    • example:
class Class1:

def __init__(self, ):

self.number = 0

def __iter__(self):

return self    # 拥有__iter__方法的对象,就为迭代器,所以自定义迭代器通常返回对象实例自己

def __next__(self):

if self.number >= 10:

raise StopIteration

else:

self.number += 2

return self.number

# 实例化并执行

obj = Class1()

for x in obj:

print(x)

二、面向对象其它:

  • isinstance(obj,Class1)
    • 查看对象是否为class1的实例,或其所创建类的父类,当class为obj的父类,或class为obj的父类的父类时,返回True
  • issubclass(class2,Class1)
    • 返回布尔值,查看class2是否为class1的子类
  • super(myclass, self).function(args)
    • 调用并执行 myclass父类中的function方法
# 经常用于执行父类中与子类同名的方法:

class C1:

def f1(self):

print(‘c1.f1‘)

class C2(C1):

def f1(self):

# 表示主动执行父类中的f1方法

super(C2,self).f1()  # 第一中方法

print(‘c2.f1‘)

obj = C2()



二、扩展:旧框架新增功能

  • 不用装饰器原因:装饰器需要在函数上方加@,即会改动源代码
  • 使用super:
    • 业务场景:
--------------------------------公司代码场景

# 老员工NB代码核心逻辑

vim backend/commons

......nb的代码,其中有个Foo类

# 程序配置文件

vim settings.py

Path = ‘bakend.commons‘ // 模块所在路径

ClassName = ‘Foo‘          //所需要的目标类

# 老员工NB代码入口

vim index.py

from settings import Path           类所在模块的路径

from settings import ClassName    所需要调用的类名

def excute():

module = __import(Path,fromlist=True)   # 从路径中找到目标模块

cls = getattr(commons, ClassName)   #  从目标模块中找到目标类

obj = cls()

obj.func1()                # 领导要求对该功能进行封装 ,该功能存在于核心逻辑中,核心逻辑文件不能修改,该入口文件也不能改,总之什么都不能改

if __nam__ == ‘__main__‘:

excute()

    • 更改:
      • 思想:
        • 通过继承的方式。来实现在老代码中添加功能
        • 即只需要继承老员工的类,对目标方法进行修改后,更改配置文件类的指向即可
      • 图示

      • 过程:
# 封装功能的文件

vim  lib.py

from backend.commons import Foo  # 导入要被封装的类

class my_class(Foo):         # 新建一个类,并继承老员工的类

def func1(self):

print(‘before‘)

super(my_class, self).func1()     //执行老员工Foo类中的原本的功能

print(‘after‘)  // 新增功能

# 修改配置文件

vim setting.py

Path = ‘lib‘

ClassName = ‘my_class‘

时间: 2024-10-07 04:49:45

特殊成员的相关文章

Java的成员变量初始化

对于方法里面的成员变量,Java要求程序员强制提供一个初始化的值.比如下面这个方法就会出错: public class Breakyizhan{ public void Z(){ int z; z++; } public static void main(String[] args) { Breakyizhan B = new Breakyizhan(); B.Z(); } } /* (www.breakyizhan.com) 输出结果是: 编译会出错,方法变量没有初始化 */ 而对于类的数据,

C++学习笔记(2)---2.5 C++函数编译原理和成员函数的实现

转载自:http://c.biancheng.NET/cpp/biancheng/view/2996.html点击打开链接 从上节的例子可以看出,对象的内存模型中只保留了成员变量,除此之外没有任何其他信息,程序运行时不知道 obj 的类型为 Demo,也不知道它还有一个成员函数 display().那么,究竟是如何通过对象调用成员函数的呢? C++函数的编译 C++和C语言的编译方式不同.C语言中的函数在编译时名字不变,或者只是简单的加一个下划线_(不同的编译器有不同的实现),例如,func()

第13条:使类和成员的可访问性最小化

区别设计良好的模块和设计不好的模块,最重要的因素在于,这个模块对于外部的其他模块而言,是否隐藏其内部数据和其他实现细节.设计良好的模块会隐藏所有的实现细节,把它的API于它的实现清晰地隔离开来.然后,模块之间通过它们的API进行通信,一个模块不需要知道其他模块的内部工作情况,这个概念称为信息隐藏或封装.使类和成员的可访问性最小化可以有效的解除系统中各个模块的耦合度.实现每个模块的独立开发.使得系统更加的可维护,更加的健壮.对于顶层的(非嵌套的)类和接口,只有两种可能的访问级别,包级私有的和公有的

(6)类型和成员基础

6.1 类型的各种成员 在一个类型中,可以定义0个或者多个以下种类的成员: 常量 常量是在编译时设置其值并且永远不能更改其值的字段.使用常量可以为特殊值提供有意义的名称以代替数字文本,以使代码变得更容易阅读及维护.定义常量请使用关键字const.private const Int32 SomeConstant = 1; 字段 字段存储着类满足其设计所必须拥有的数据.例如,表示日历日期的类可能有三个整数字段:一个表示月份,一个表示日期,还有一个表示年份.强烈建议将字段声明为私有字段,防止类型的状态

Delegate成员变量和Event的区别

上周五有同事问了我一个问题:Delegate和Event有什么区别?具体来说在设计一个类的时候,声明一个事件(Event)和声明一个Delegate类型的成员变量有啥区别. 我的第一反应是没啥区别,虽然从语法看起来不一样,但从代码希望达成的效果来看是一致的,本质都是回调函数.当然区别是肯定有的,我能给我的理由是两个:首先从与COM交互操作时,event对应COM接口中的事件:其次VS的编译环境对定义event提供了更加便捷的支持,可以为其自动生成回调函数的框架. 翻了翻MSDN,并没有直接描述两

C# 字段、属性、成员变量 [转载]

一.定义与作用 1.字段(field):是C#类级别定义的,和方法同一级别. 一般用来类内部进行访问,充当一种类中的"全局变量"角色:或者配合属性来使用 2.属性:同样是C#类级别定义的,一般是供外部类访问的. 3.成员变量:"全局变量",在类中定义的变量,区别于在方法中定义的局部变量.它与字段属性不是同一级别概念,字段,属性都可以叫做成员变量. 二.使用 class Basic { private string FieldVar;//这是字段,在当前类中调用 pr

Java接口里定义成员变量 说明

首先你要弄清接口的含义.接口就是提供一种统一的'协议',而接口中的属性也属于'协议'中的成员.它们是公共的,静态的,最终的常量.相当于全局常量. 在interface里面的变量都是public static final 的.所以你可以这样写: public static final int i=10; 或则 int i=10;(可以省略掉一部分,在接口里的成员变量默认就是public static final) 注意在声明的时候要给变量赋予初值 解释: 首先你要弄清接口的含义.接口就是提供一种统

成员变量的定义与使用

成员变量又称为成员属性,它是描述对象状态的数据,是类中很重要的组成成分.本节详细讨论如何来定义成员变量.成员变量的访问权限,以及静态成员变量与实例成员变量之间的区别. 成员变量的定义 定义成员变量的语法如下:[变量修饰符] 类型说明符变量名类的成员变量和在方法中所声明的局部变量都是用户标识符,它们的命名规则相同.变量修饰符是可选项,一个没有变量修饰符的变量定义如下: public class Cuber{ double width,height; int number; } 成员变量的类型可以是

通过指针访问C++对象的私有成员

C++对象的私有成员是禁止类外的访问的.但是我们仍然可以通过指针访问C++对象的私有成员. #include <iostream> using namespace std; class A { public: A(int i = 0) :m_i(i) {} void print() { cout << "m_i" << this->m_i << endl; } private: int m_i; }; int main(int ar

第3周项目5-数组作数据成员(4)

* * Copyright (c) 2015, 烟台大学计算机学院 * All rights reserved. * 文件名称:test.cpp * 作 者:刘畅 * 完成日期:2015年 3 月 22 日 * 版 本 号:v1.0 * * 问题描述: 阅读教材P255例8.4,注意到类中的数据成员可以是数组.设计一个工资类(Salary),其中类的数据成员如下: class Salary { private: double salarys[50]; //多人的工资 int number; //