Позвольте мне представить свой подход под названием Yappi . Он относится к генераторам производного класса Runtime proxy, добавляя новые функции к существующему объекту или типу, например Dynamic Proxy от Caste Project.
Он позволяет реализовать INotifyPropertyChanged один раз в базовом классе, а затем объявлять производные классы в следующих стиль, поддерживающий INotifyPropertyChanged для новых свойств:
public class Animal:Concept
{
protected Animal(){}
public virtual string Name { get; set; }
public virtual int Age { get; set; }
}
Сложность построения производного класса или прокси может быть скрыта за следующей строкой:
var animal = Concept.Create.New();
И вся работа по реализации INotifyPropertyChanged может сделайте это следующим образом:
public class Concept:INotifyPropertyChanged
{
//Hide constructor
protected Concept(){}
public static class Create where TConcept:Concept
{
//Construct derived Type calling PropertyProxy.ConstructType
public static readonly Type Type = PropertyProxy.ConstructType>(new Type[0], true);
//Create constructing delegate calling Constructor.Compile
public static Func New = Constructor.Compile>(Type);
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(PropertyChangedEventArgs eventArgs)
{
var caller = PropertyChanged;
if(caller!=null)
{
caller(this, eventArgs);
}
}
//define implementation
public class Implementation : DefaultImplementation where TConcept:Concept
{
public override Func OverrideGetter(PropertyInfo property)
{
return PropertyImplementation.GetGetter(property.Name);
}
///
/// Overriding property setter implementation.
///
/// Base type for implementation. TBaseType must be TConcept, and inherits all its constraints. Also TBaseType is TDeclaringType.
/// Type, declaring property.
/// Constructed type. TConstructedType is TDeclaringType and TBaseType.
/// Type of property.
/// PropertyInfo of property.
/// Delegate, corresponding to property setter implementation.
public override Action OverrideSetter(PropertyInfo property)
{
//This code called once for each declared property on derived type's initialization.
//EventArgs instance is shared between all events for each concrete property.
var eventArgs = new PropertyChangedEventArgs(property.Name);
//get delegates for base calls.
Action setter = PropertyImplementation.GetSetter(property.Name);
Func getter = PropertyImplementation.GetGetter(property.Name);
var comparer = EqualityComparer.Default;
return (pthis, value) =>
{//This code executes each time property setter is called.
if (comparer.Equals(value, getter(pthis))) return;
//base. call
setter(pthis, value);
//Directly accessing Concept's protected method.
pthis.OnPropertyChanged(eventArgs);
};
}
}
}
Он полностью безопасен для рефакторинга, не использует отражения после построения типа и достаточно быстро.
Как вы добавляете любую переменную экземпляра, self.func = func
:
class Objective():
def __init__(self, function):
if isinstance(function, str):
def func(x): # no need for self
return eval(function, locals())
self.func = func # here
elif callable(function):
self.func = function
def __call__(self, x):
return self.func(x)
Обратите внимание, вам не нужно self
в вашем определении func
. Также обратите внимание, что вы нигде не использовали анонимную функцию. Вы использовали нормальное определение функции.
Наконец, (хотя вы, вероятно, не должны этого делать), вам нужно получить x
в пространствах имен, доступных для eval
, так что-то вроде:
return eval(function, locals())