Они - волшебство позади целого набора базовых функций Python.
при использовании отмеченного точкой доступа для поиска участника (например, x.y), Python сначала ищет участника в словаре экземпляра. Если это не найдено, это ищет его в словаре класса. Если это находит его в словаре класса, и объект реализует протокол дескриптора, вместо того, чтобы просто возвратить его, Python выполняет его. Дескриптор является любым классом, который реализует __get__
, __set__
, или __delete__
методы.
Вот то, как Вы реализовали бы свою собственную версию (только для чтения) свойства с помощью дескрипторов:
class Property(object):
def __init__(self, fget):
self.fget = fget
def __get__(self, obj, type):
if obj is None:
return self
return self.fget(obj)
и Вы использовали бы его точно так же, как встроенное свойство ():
class MyClass(object):
@Property
def foo(self):
return "Foo!"
Дескрипторы используются в Python для реализации свойств, связанных методов, статических методов, методов класса и слотов, среди других вещей. Понимание их облегчает видеть, почему большим количеством вещей, которые ранее были похожи на Python 'причуды', является способ, которым они.
Raymond Hettinger имеет превосходное учебное руководство , которое делает намного лучшее задание описания их, чем я.
Либо создать выделенный картограф, используя словарь (согласно Мехрдаду ответ) или реализовать TypeConverter .
Ваш пользовательский TypeConverter может либо заменить "" -> "_"
(и наоборот), либо он может отражать перечисление и использовать атрибут для определения отображаемого текста элемента.
enum Operation
{
[DisplayName("Equals")]
Equals,
[DisplayName("Not Equals")]
Not_Equals,
[DisplayName("Less Than")]
Less_Than,
[DisplayName("Greater Than")]
Greater_Than
};
public class OperationTypeConverter : TypeConverter
{
private static Dictionary<string, Operation> operationMap;
static OperationTypeConverter()
{
BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.GetField
| BindingFlags.Public;
operationMap = enumType.GetFields(bindingFlags).ToDictionary(
c => GetDisplayName(c)
);
}
private static string GetDisplayName(FieldInfo field, Type enumType)
{
DisplayNameAttribute attr = (DisplayNameAttribute)Attribute.GetCustomAttribute(typeof(DisplayNameAttribute));
return (attr != null) ? attr.DisplayName : field.Name;
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
string stringValue = value as string;
if (stringValue != null)
{
Operation operation;
if (operationMap.TryGetValue(stringValue, out operation))
{
return operation;
}
else
{
throw new ArgumentException("Cannot convert '" + stringValue + "' to Operation");
}
}
}
}
Эту реализацию можно улучшить несколькими способами:
Вау. Сюрприз! В документации для MessageFormat известен ответ:
В String ,
"''"
представляет собой одинарная кавычка. A QuotedString может содержать произвольные символы, кроме одинарные кавычки; окружающий сингл цитаты удаляются. An UnquotedString может содержать произвольные символы кроме одинарных кавычек и фигурных скобок слева кронштейны. Таким образом, строка, которая должна результат в форматированном сообщении"'{0}'"
можно записать как"'' '{' 0} ''"
или"'' '{0}' ''"
.
Используйте одинарные кавычки:
MessageFormat.format(" public {0} get{1}() '{'return {2};'}'\n\n",
type, upperCamel, lowerCamel);
Если вы действительно хотите использовать одинарные кавычки, просто удвойте их. JavaDoc для MessageFormat
дает следующий довольно сложный пример:
Таким образом, строка, которая должна приводить к форматированное сообщение
"'{0}'"
может быть записывается как"'' '{' 0} ''" или "'' '{0}' ''"
.
Это ''
для одинарной кавычки, затем '{'
для закрывающей скобки, затем 0
, '}'
для закрывающей фигурной скобки и ''
для закрывающей кавычки .