Ventajas de Python en Wizards
1. metaclase
Hay un par en el código fuente de PyPy y extendabletype
"""
Dos trucos de magia para las clases:
Clase X:
__metaclass__ = extendabletype
...
# En otros archivos. ..
class __extend__(X):
... # Aquí puedes agregar nuevos métodos y atributos de clase a X
Lo más útil es el segundo truco , que le permite construir
métodos cuyo "yo" sea un par de objetos, no solo uno:
clase __extend__(pairtype(X, Y)):
atributo = 42
método def((x, y), otros, argumentos):
método def((x, y), otros, argumentos de clase):
.....
par(x, y).atributo
par(x, y).método( otros, argumentos)
Esto buscará métodos y atributos de clase basados en las
clases reales de los dos objetos que entran en pair() y usará los métodos (emparejados) en la subclase/Reglas generales para la sobrecarga de propiedades p>
Para obtener más información, consulte test_pairtype."""
class extendabletype(type.):
"""Un tipo con un truco de sintaxis: 'class __extend__( t)' en realidad extiende
la definición de 't' en lugar de crear una nueva subclase.
"""
def __new__(cls, nombre, bases, dict):
if nombre == '__ extend__':
para cls en bases:
para clave, valor en dict.items():
if key == '__module__':
continuar
# XXX ¿Necesitamos proporcionar algo más para el decapado?
setattr(cls, key, value)
return Ninguno
else:
return super(extendabletype, cls).__new__(cls, name, bases, dict)
def pair(a, b):
"""Devuelve un objeto de par.""
tp = pairtype(a.__class__, b.__class__)
return tp((a, b))# tp es una subclase de tupla
pairtypecache = {}
def tipo de par(cls1, cls2):
""""tipo(par(a, b)) es tipo de par(a.__class__, b. __class__)
""""tipo(par(a, b)) es tipo de par(a.__ clase__, b.__clase__).""""
prueba: p>
par = pairtypecache[cls1, cls2]
excepto KeyError:
nombre = 'pairtype(s, s)' (cls1.__name__, cls2.
bases1 = [tipo de par(base1, cls2) para base1 en cls1.__bases__]
bases2 = [tipo de par(cls1, base2) para base2 en cls2.__bases__]
bases = tupla (bases1 bases2) o (tupla,) # 'tupla': base definitiva
par = partipocache[cls1, cls2] = tipo extensible(nombre, bases, {})
devolver par
Primero, hablemos del tipo extensible. En realidad, es una implementación de Python de la clase media de C#, como se indica claramente en los comentarios.
Luego están el par y el tipo de par. pairtype crea una nueva clase basada en dos clases que hereda de pairtype (una forma indirecta de decir...) o una tupla construida usando las clases base de ambas clases.
¿Para qué se utiliza? Se puede utilizar para implementar múltiples métodos.
clase __extend__(pairtype(int, int)):
def foo((x, y)):
print 'int-int: p>
p>
clase __ extend__(pairtype(bool, bool)):
def bar((x, y)):
print 'bool- bool: s-s' ( x, y)
par(False, True).foo() # imprime 'int-int: False, True'
par(123, True) .foo() # imprime 'int-int: 123, Verdadero'
pair(False, True).bar() # imprime 'bool-bool:
par(123, True).bar() # Vaya, no existe tal método
En este ejemplo, la metaclase parece ser solo una función de apoyo, la diversión está en este par...
Uno más.
clase GameObjectMeta(tipo):
def __new__(mcls, clsname, bases, _dict):
para k, v en _dict.items():
if isinstance(v, (list, set)):
_dict[k] = tuple(v) # No se permiten objetos mutables
cls = type.__new__(mcls, clsname, bases, _dict)
all_gameobjects. add(cls)
para b en bases:
game_objects_hierarchy.add((b , cls))
Devuelve cls
@staticmethod
def _dump_ gameobject_hierarchy():
con open('/dev/shm /gomap.dot', 'w') as f:
f.write('digraph {\nrankdir=LR;\n')
f.write('\n '.join([
'"s" -gt; "s";' (a.__name__, b.__name__)
para a, b en game_objects_hierarchy
]))
f.write('}')
def __setattr__(cls, campo, v):
tipo.__setattr__(cls , campo, v)
if campo in ('ui_meta', ):
return
log.warning('SetAttr: s.s = s' (cls .__name__, field, repr(v)))
Este es un fragmento de código tomado del juego Triple Triad que escribí (haga clic en el enlace en mi firma).
La idea general es reemplazar todos los contenedores mutables de la clase con contenedores inmutables y luego registrar la relación de herencia.
Una vez me engañó este problema. El valor de la clase lo disfruta el dios global. El código lógico modificó accidentalmente el valor de la clase. prueba y luego fue colocado en la fila..... Es una tragedia... En ese momento, me devané los sesos pero no esperaba que este problema volviera a... Después de descubrir el problema, agregué esto y no se permitió la modificación de cosas en la clase.
El registro de relaciones de herencia es para diagramas de clases.
Entonces la inyección de datos habitual
metadata = {}
def gen_metafunc(_for):
def metafunc(clsname, bases, _dict):
meta_for = getattr(_for, clsname)
meta_for.ui_meta = UIMetaDescriptor()
si meta_for en metadatos:
generar excepción (redefinición de ui_meta!' meta_for)
metadata[meta_for] = _dict
devolver metafunc
de gamepack.thb importar personajes p >
__metaclass__ = gen_ metafunc(characters.sakuya)
clase Sakuya:
# Entonces esto no es una clase, se almacena como datos en metadatos dict
char_name = u's 'Sakuya Sixteen'
port_image = 'thb-portrait-sakuya'
figure_image = 'thb-figure-sakuya'
miss_sound_effect = 'thb-cv-sakuya_miss'
descripción = (
u'|DB Totally Dashing PAD Long 16 Nights Sakuya Stamina:
u'|G Lunar Reloj|r: |B Técnica de bloqueo|r, Al comienzo de la fase de preparación, realizas una fase de juego adicional \u'|G Flying Dagger|r: Puedes usar una carta equipada como catapulta O hay. No hay límite de distancia cuando se utiliza como catapulta.
\n\n'
u'|DB (Artista: Little D@Star's Delusional Country, CV: VV)|r'
)
Ruby Don No envíes spam, sé que puedes hacerlo de forma más elegante...
2. Escape del sandbox de Python
pile(code, mod.__file__, 'exec ')
exec(co, mod.__dict__)
devolver mod
excepto excepción como e:
UnityEngine.Debug.LogError ('Error_file__, ' exec')
print '¡Foo!', self.value
foo = Foo(1)
foo.foo() # ¡Foo! 1
foos = BatchList(Foo(i) para i en xrange(10))
foos.value # BatchList([0, 1, 2, 3, ..., 9])
foos.foo() # Puedes adivinar
foos.foo() # ¡Foo!