python类的命名空间_【python类】类

1. 类的命名空间

1> 简单变量和属性名称

1. 简单变量名(无点号):遵循函数LEGB作用域法则

==> 赋值(X = value):// 使变量成为本地变量:除非声明是全局的

==> 引用(X):// LEGB搜索变量

2. 属性名称(点号属性名称):遵循模块和类的规则

==> 赋值(object.X = value) // 实例对象命名空间内创建、修改变量

==> 引用(object.X):// 基于类的对象:对象内遵循继承搜索;模块:对象中直接读取X(模块中存在类对象,模块没有继承的概念)

2> 命名空间组成:命名空间字典和命名空间链接

属性点号运算实际是内部字典的取值; // x.data = x.__dict__['data']

x.__dict__ // 获取实例的命名空间

x.__class__ // 获取实例的父类

sub.__bases__ // sub类的父类

命名空间链接:当前命名空间找不到,会按照继承搜索查找

"""

父类层次:

B: B --> A

F: F --> D --> B --> A --> C --> A --E

"""

class A: pass

class B(A): pass

class C(A): pass

class D(B,C): pass

class E: pass

class F(D,E): pass

2. 继承

*继承原理:实际也是继承树的应用,子类实例总是先去查找自己的命名空间,然后才去查找父类命名空间*

class Manager(Person):

# 7 调用父类的构造函数:我们可以决定哪些参数使用父类,比如此处的Job

def __init__(self,name,pay):

Person.__init__(self,name,'mgr',pay)

def givePay(self,percent,bouns=.10):

# 调用方法两种方式 1) 实例.方法() 2)类.方法(self) 不管哪种,方法都需要传递一个self调用

Person.givePay(self,percent + bouns)

# 6.2 继承:扩展子类行为,只能在子类实例对象使用

def doSomething(self):

return '[%s %s]' %(self.__class__.__name__,"考核")

"""

# coding:utf-8

"""

类的继承

"""

class Employees:

def __init__(self,name,salary=0):

self.name = name

self.salary = salary

def givePay(self,percent):

self.salary = self.salary + (self.salary * percent)

def work(self):

print(self.name,"does stuff")

def __repr__(self):

return "" %(self.name,self.salary)

class Chef(Employees):

def __init__(self,name):

Employees.__init__(self,name,50000)

def work(self):

print(self.name,'make foods')

class Server(Employees):

def __init__(self,name):

Employees.__init__(self,name,40000)

def work(self):

print(self.name,'interfaces to customer')

class PizzaRobbt(Chef):

def __init__(self,name):

Chef.__init__(self,name)

def work(self):

print(self.name,'make pizza')

if __name__ == "__main__":

# 一定要分清楚:object.attr 和 赋值

# 继承是从点号运算开始的,触发实例、类以及超类中属性搜索

bob = PizzaRobbt('bob')

print(bob)

bob.work()

bob.givePay(0.2)

print(bob)

for kclass in Employees,Chef,Server,PizzaRobbt:

# kclass.__name__ 是一个字符串

obj = kclass(kclass.__name__)

obj.work()

"""

"""

"""

类的组合:order下单包含Server、Customer、PizzaRobbt一起完成一件事情.

"""

from employees import Server,PizzaRobbt

class Customer:

def __init__(self,name):

self.name = name

def order(self,server):

print(self.name,"order pizza",server)

def pay(self,server):

print(self.name,'pay money',server)

class Oven:

def bake(self):

print('ovens bakes')

class PizzaShop:

def __init__(self):

self.server = Server('Pat')

self.chef = PizzaRobbt('bob')

self.oven = Oven()

def order(self,name):

customer = Customer(name)

customer.order(self.server)

self.chef.work()

self.oven.bake()

customer.pay(self.server)

if __name__ == "__main__":

scene = PizzaShop()

scene.order('tom')

"""

3. 抽象超类

*父类中的方法具体在子类中实现;抽象超类是不能被继承的,除非所有抽象方法都在子类实现*

"""

class Super:

def method(self):

print("in Super.method")

def delegate(self):

self.action()

# 要是子类没有提供action,那么就会抛错:采用assert

# assert False,'action must be method!'

class Provider(Super):

def method(self):

print('starting Sub.method')

Super.method(self) // 扩展父类的方法

print('ending Sub.method')

def action(self): // 实现父类的抽象方法

print('In Provider.action')

"""

4. 运算符重载

# coding:utf-8

"""

运算符重载

"""

import operator

class Number:

# 1. 拦截构造方法

def __init__(self,data):

self.data = data

# 2. 拦截减法运算

def __sub__(self, other):

return Number(self.data - other)

class Indexer:

def __init__(self,data):

self.data = data

# 3.1 拦截索引、切片操作:实例对象拥有索引、切片操作

# 3.1 重载迭代:每次迭代实例对象时都会调用该方法,传入索引值

def __getitem__(self, item):

print('getitem:',item)

return self.data[item]

# 3.2 拦截索引赋值、切片赋值操作:实例对象拥有索引赋值、切片赋值操作

def __setitem__(self, key, value):

self.data[key] = value

class Squeres:

"""

iter() 迭代器工厂函数

__iter__() 迭代器协议,可以在自定义类里面形成迭代器 调用方式 1:手动next(i)调用 2:可迭代环境调用

可迭代对象:可以用迭代环境循环的对象

迭代器:支持迭代协议(也就是可以使用next调用);迭代器是可以记住状态的

可迭代对象不一定是迭代器 (for i in 'spam':)

迭代器一定是可迭代对象(支持在迭代环境循环调用)

"""

def __init__(self,start,stop):

self.value = start - 1

self.stop = stop

# 3.3 在任何迭代环境中,会优先调用__iter__;之后调用__getitem__

# __iter__调用迭代协议;__getitem__调用索引取值,知道抛出索引超范

# __iter__ 根本没有重载索引表达式:X = Squeres(1,5) X[1] 报错

# __iter__ 只循环一次: X = Squeres(1,5) [for i in X] ==> 第二次迭代会为空

def __iter__(self): # 定义了__iter__的方法,类实例是可迭代对象

return self # 此处返回self,每次生成的可迭代对象只能调用一次

def __next__(self):

if self.value == self.stop:

raise StopIteration

self.value += 1

return self.value

# 调用next方法

class SkipIterator:

def __init__(self,wrapper):

self.wrapper = wrapper

self.offset = 0

def __next__(self):

if self.offset >= len(self.wrapper):

raise StopIteration

item = self.wrapper[self.offset]

self.offset += 2

return item

# 返回迭代器对象

class SkipObject:

def __init__(self,wrapper):

self.wrapper = wrapper

def __iter__(self):

return SkipIterator(self.wrapper)

class Iter1:

"""

1. 成员关系:contains(映射) --> iter --> getitem

2. __iter__和__getitem__ 都可捕获迭代环境

区别:1 __iter__ 使用迭代协议获取值(__next__),且可以保持状态信息;__getitem__ 使用索引获取值

2 __getitem__ 可以支持索引和切片操作

3 当字段索引行数据时(list、tuple),两者可替换;为hash类型时(dict、set),只能用__iter__

"""

def __init__(self,value):

self.value = value

def __getitem__(self, item):

print("getitem:",item)

return self.value[item]

def __iter__(self):

print("iter=>",end="")

self.offset = 0

return self

def __next__(self):

print("next:",end="")

if self.offset == len(self.value):

raise StopIteration

item = self.value[self.offset]

self.offset += 1

return item

def __contains__(self, item):

print("contanins: ",end='')

return item in self.value

class Library(object):

def __init__(self):

self.books = {'title': 'a', 'title2': 'b', 'title3': 'c', }

def __getitem__(self, i):

return self.books[i]

def __iter__(self):

# 方法1 使用生成器

for titles in self.books:

yield self.books[titles]

class Empty:

"""

拦截属性点号操作;

如果python可以在继承树(self.__dict__)找到该属性,那么__getattr__方法不会被调用

赋值:self.attr = value ==> self.__setattr__(attr,value)

"""

def __init__(self):

self.data = 0

def __getattr__(self, item):

if item == "age":

print("__getattr__:",item,end=" ")

return 40

else:

raise AttributeError(item)

def __setattr__(self, key, value):

if key == "data":

# 此处一定用self.__dict__[key] = value

# 因此在__setattr__里面赋值,会再调用__setattr__,造成内存溢出

self.__dict__[key] = value

else:

raise AttributeError(key + "not allowed")

class A:

"""

1.

__add__ 原处加法(a + b ;a += 1)

__radd__ 右侧加法

2.

a + b ,python会先去a里面找__add__,找不到会去__radd__查找

这个例子: b + a 会报错,因为python会先去B找__add__,然后去A找__radd__,均不满足

3. 每个二元运算符都支持:包括 __sub__(减法)

"""

def __init__(self,val):

self.val = val

def __add__(self, other):

return self.val + other

class B:

def __init__(self,val):

self.val = val

def __radd__(self, other):

return self.val + other

class Callee:

"""

编写api接口常用:可以将类和实例调用当作函数来使用,并且可以将实例的状态保留到函数内部,自然而然成为了被一个函数记住

==>并调用另一个函数的实现

__call__ 任何定义了该方法的类和实例 支持与常规函数一致的调用

c = Callee()

c(1,2,3) ==> __call__ (1,2,3) {}

"""

def __call__(self, *args, **kwargs):

print("__call__,",args,kwargs)

class CallBack:

def __init__(self,color):

self.color = color

def __call__(self):

print('turn',self.color)

class BiJiao:

"""

比较:__lt__ __gt__ __cmp__(python3.0失效,使用operator替代)

"""

pass

class Bool1:

"""

拦截布尔操作

__bool__ >> __len__

python 3.0 优先尝试__bool__ python 2.6优先尝试__len__

"""

def __bool__(self):

return True

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值