pythoncharm_pythoncharm有哪些奇技淫巧

展开全部

1. 元类(metaclass)

PyPy的源2113码里有个pair和extendabletype

"""

Two magic tricks for classes:

class X:

__metaclass__ = extendabletype

...

# in some other file...

class __extend__(X):

... # and here you can add new methods and class attributes to X

Mostly useful together with the second trick, which lets you build

methods whose 'self' is a pair of objects instead of just one:

class __extend__(pairtype(X, Y)):

attribute = 42

def method((x, y), other, arguments):

...

pair(x, y).attribute

pair(x, y).method(other, arguments)

This finds methods and class attributes based on the actual

class of both objects that go into the pair(), with the usual

rules of method/attribute overriding in (pairs of) subclasses.

For more information, see test_pairtype.

"""

class extendabletype(type):

"""A type with a syntax trick: 'class __extend__(t)' actually extends

the definition of 't' instead of creating a new subclass."""

def __new__(cls, name, bases, dict):

if name == '__extend__':

for cls in bases:

for key, value in dict.items():

if key == '__module__':

continue

# XXX do we need to provide something more for pickling?

setattr(cls, key, value)

return None

else:

return super(extendabletype, cls).__new__(cls, name, bases, dict)

def pair(a, b):

"""Return a pair object."""

tp = pairtype(a.__class__, b.__class__)

return tp((a, b)) # tp is a subclass of tuple

pairtypecache = {}

def pairtype(cls1, cls2):

"""type(pair(a,b)) is pairtype(a.__class__, b.__class__)."""

try:

pair = pairtypecache[cls1, cls2]

except KeyError:

name = 'pairtype(%s, %s)' % (cls1.__name__, cls2.__name__)

bases1 = [pairtype(base1, cls2) for base1 in cls1.__bases__]

bases2 = [pairtype(cls1, base2) for base2 in cls2.__bases__]

bases = tuple(bases1 + bases2) or (tuple,) # 'tuple': ultimate base

pair = pairtypecache[cls1, cls2] = extendabletype(name, bases, {})

return pair

先说extendabletype。5261嘛 其实注释已经4102说得听明白了,1653就是一个C#里面的partial class的Python实现。

然后是pair和pairtype。pairtype就是根据两个类创建一个新的类,这个类继承自使用这两个类的基类构造的pairtype(有点绕……)或者tuple。

有啥用呢?可以拿来实现multimethod。

class __extend__(pairtype(int, int)):

def foo((x, y)):

print 'int-int: %s-%s' % (x, y)

class __extend__(pairtype(bool, bool)):

def bar((x, y)):

print 'bool-bool: %s-%s' % (x, y)

pair(False, True).foo() # prints 'int-int: False, True'

pair(123, True).foo() # prints 'int-int: 123, True'

pair(False, True).bar() # prints 'bool-bool: False, True'

pair(123, True).bar() # Oops, no such method

好像这个例子里元类只是个打辅助的角色,好玩的都在那个pair里……

再换一个。

class GameObjectMeta(type):

def __new__(mcls, clsname, bases, _dict):

for k, v in _dict.items():

if isinstance(v, (list, set)):

_dict[k] = tuple(v) # mutable obj not allowed

cls = type.__new__(mcls, clsname, bases, _dict)

all_gameobjects.add(cls)

for b in bases:

game_objects_hierarchy.add((b, cls))

return cls

@staticmethod

def _dump_gameobject_hierarchy():

with open('/dev/shm/gomap.dot', 'w') as f:

f.write('digraph {\nrankdir=LR;\n')

f.write('\n'.join([

'"%s" -> "%s";' % (a.__name__, b.__name__)

for a, b in game_objects_hierarchy

]))

f.write('}')

def __setattr__(cls, field, v):

type.__setattr__(cls, field, v)

if field in ('ui_meta', ):

return

log.warning('SetAttr: %s.%s = %s' % (cls.__name__, field, repr(v)))

这个是从我写的三国杀游戏中提取的一段代码(点我签名上的链接)。大意就是把class上所有可变的容器都换成不可变的,然后记录下继承关系。

曾经被这个问题坑过,class上的值是全局共享的,逻辑代码一不小心修改了class上的值,单机测试的时候是测不出来的,然后放到线上……就悲剧了……当时绞尽脑汁没有想到是这个问题硬生生的回滚了……发现了问题之后就加上了这个东西,不允许修改class上的东西。

记录下继承关系是为了画类图。

还有就是常用的做数据注入

metadata = {}

def gen_metafunc(_for):

def metafunc(clsname, bases, _dict):

meta_for = getattr(_for, clsname)

meta_for.ui_meta = UIMetaDescriptor()

if meta_for in metadata:

raise Exception('%s ui_meta redefinition!' % meta_for)

metadata[meta_for] = _dict

return metafunc

from gamepack.thb import characters

__metaclass__ = gen_metafunc(characters.sakuya)

class Sakuya:

# 于是这个就不是类了, 而是作为数据存到了metadata这个dict里

char_name = u'十六夜咲夜'

port_image = 'thb-portrait-sakuya'

figure_image = 'thb-figure-sakuya'

miss_sound_effect = 'thb-cv-sakuya_miss'

description = (

u'|DB完全潇洒的PAD长 十六夜咲夜 体力:4|r\n\n'

u'|G月时计|r:|B锁定技|r,准备阶段开始时,你执行一个额外的出牌阶段。\n\n'

u'|G飞刀|r:你可以将一张装备牌当【弹幕】使用或打出。按此法使用的【弹幕】无距离限制。\n\n'

u'|DB(画师:小D@星の妄想乡,CV:VV)|r'

)

Ruby党不要喷,我知道你们可以做的更优雅……

2. Python沙盒逃逸

刷新三观的Python代码

3. PEP302 New Import Hook

最近在把刚才提到的纯Python游戏向Unity引擎上移植。

玩过Unity的就会知道,Unity的游戏的资源都是打包在一起的,没有单独的文件,Python解释器就不高兴了……于是写了import hook,用Unity提供的API来读py文件。

# -*- coding: utf-8 -*-

# -- stdlib --

import imp

import sys

# -- third party --

# -- own --

from clr import UnityEngine, WarpGateController

# -- code --

class UnityResourceImporter(object):

known_builtin = (

'sys',

'imp',

'cStringIO',

'gevent_core',

'gevent_ares',

'gevent_util',

'gevent_semaphore',

'msgpack_packer',

'msgpack_unpacker',

'UnityEngine',

)

def __init__(self, bases, unity_loader):

self.bases = bases

self.last_fullname = ''

self.last_text = ''

self.last_ispkg = False

self.unity_load = unity_loader

def find_module(self, fullname, path=None):

if fullname in sys.modules:

return self

head = fullname.split('.')[0]

if head in self.known_builtin:

return None

rst = self.do_load_module(fullname)

if rst:

self.last_text, self.last_ispkg = rst

self.last_fullname = fullname

return self

else:

return None

def load_module(self, fullname):

if fullname in sys.modules:

return sys.modules[fullname]

if fullname != self.last_fullname:

self.find_module(fullname)

try:

code = self.last_text

ispkg = self.last_ispkg

mod = sys.modules.setdefault(fullname, imp.new_module(fullname))

mod.__file__ = "" % fullname

mod.__loader__ = self

if ispkg:

mod.__path__ = []

mod.__package__ = fullname

else:

mod.__package__ = fullname.rpartition('.')[0]

co = compile(code, mod.__file__, 'exec')

exec(co, mod.__dict__)

return mod

except Exception as e:

UnityEngine.Debug.LogError('Error importing %s %s' % (fullname, e))

raise ImportError(e)

def do_load_module(self, fullname):

fn = fullname.replace('.', '/')

asset = self.try_load(fn + '.py')

if asset is not None:

return asset, False

asset = self.try_load(fn + '/__init__.py')

if asset is not None:

return asset, True

def try_load(self, filename):

for b in self.bases:

asset = self.unity_load(b + filename)

if asset is not None:

return asset

return None

sys.meta_path.append(UnityResourceImporter([

'Python/THBattle/',

'Python/Site/',

'Python/Stdlib/',

], WarpGateController.GetTextAsset))

需要的extension module都静态编译到解释器里了,所以没考虑。

4. 可以批量执行操作的list

class BatchList(list):

def __getattribute__(self, name):

try:

list_attr = list.__getattribute__(self, name)

return list_attr

except AttributeError:

pass

return list.__getattribute__(self, '__class__')(

getattr(i, name) for i in self

)

def __call__(self, *a, **k):

return list.__getattribute__(self, '__class__')(

f(*a, **k) for f in self

)

class Foo(object):

def __init__(self, v):

self.value = v

def foo(self):

print 'Foo!', self.value

foo = Foo(1)

foo.foo() # Foo! 1

foos = BatchList(Foo(i) for i in xrange(10))

foos.value # BatchList([0, 1, 2, 3, ..., 9])

foos.foo() # 你能猜到的

这个其实不算很黑魔法了,只是感觉很好用也有些危险,所以放上来。

暂时就想到这么多了,以后发现了再补。

本回答由提问者推荐

2Q==

已赞过

已踩过<

你对这个回答的评价是?

评论

收起

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值