Консенсус заключается в использовании словаря для этого - см. другие ответы. Это хорошая идея для большинства случаев, однако есть много аспектов, связанных с этим:
Тем не менее, я реализовал variable variables manager -класс, который предоставляет некоторые из вышеперечисленных идей. Он работает для python 2 и 3.
Вы использовали бы класс следующим образом:
from variableVariablesManager import VariableVariablesManager
myVars = VariableVariablesManager()
myVars['test'] = 25
print(myVars['test'])
# define a const variable
myVars.defineConstVariable('myconst', 13)
try:
myVars['myconst'] = 14 # <- this raises an error, since 'myconst' must not be changed
print("not allowed")
except AttributeError as e:
pass
# rename a variable
myVars.renameVariable('myconst', 'myconstOther')
# preserve locality
def testLocalVar():
myVars = VariableVariablesManager()
myVars['test'] = 13
print("inside function myVars['test']:", myVars['test'])
testLocalVar()
print("outside function myVars['test']:", myVars['test'])
# define a global variable
myVars.defineGlobalVariable('globalVar', 12)
def testGlobalVar():
myVars = VariableVariablesManager()
print("inside function myVars['globalVar']:", myVars['globalVar'])
myVars['globalVar'] = 13
print("inside function myVars['globalVar'] (having been changed):", myVars['globalVar'])
testGlobalVar()
print("outside function myVars['globalVar']:", myVars['globalVar'])
Если вы хотите разрешить переписывание переменных с помощью только тот же тип:
myVars = VariableVariablesManager(enforceSameTypeOnOverride = True)
myVars['test'] = 25
myVars['test'] = "Cat" # <- raises Exception (different type on overwriting)
Связывание обычно не работает с полями. Большинство привязок основаны, в частности, на модели ComponentModel PropertyDescriptor
, которая (по умолчанию) работает над свойствами. Это дает возможность уведомлений, проверки и т. Д. (Ни одна из которых не работает с полями).
По другим причинам, по которым я могу пойти, открытые поля - плохая идея. Они должны быть свойствами, фактом. Аналогично, изменчивые структуры - очень плохая идея. Не в последнюю очередь это защищает от непредвиденных потерь данных (обычно связанных с изменчивыми структурами). Это должен быть класс:
[DataContract]
public class StatusInfo
{
[DataMember] public int Total {get;set;}
[DataMember] public string Authority {get;set;}
}
Теперь он будет вести себя так, как вы думаете. Если вы хотите, чтобы это была неизменяемая структура, это было бы нормально (но привязка к данным была бы в одностороннем порядке, конечно):
[DataContract]
public struct StatusInfo
{
[DataMember] public int Total {get;private set;}
[DataMember] public string Authority {get;private set;}
public StatusInfo(int total, string authority) : this() {
Total = total;
Authority = authority;
}
}
Однако я бы сначала спросил, почему это структуры в первую очередь. Редактировать структуру на языках .NET очень редко. Имейте в виду, что прокси-сервер WCF «mex» будет создавать его как класс у потребителя в любом случае (если вы не используете совместное использование сборок).
В ответ на ответ «зачем использовать структуру» ответ ( «unknown (google)»):
Если это ответ на мой вопрос, это неправильно во многих отношениях. Во-первых, типы значений как переменные обычно выделяются (сначала) в стеке. Если они попадают в кучу (например, в массиве / списке), нет большой разницы в накладных расходах от класса - небольшой бит заголовка объекта плюс ссылка. Структуры всегда должны быть маленькими. Что-то с несколькими полями будет чрезмерно крупным и будет либо убивать ваш стек, либо просто вызвать медленность из-за блуждания. Кроме того, структуры должны быть неизменными - если вы действительно не знаете, что делаете.
Практически все, что представляет объект, должно быть бескомпромиссным.
Если вы попадаете в базу данных, скорость struct vs class является не-проблемой по сравнению с выходом из процесса и, вероятно, по сети. Даже если это немного медленнее, это ничего не значит по сравнению с тем, что нужно сделать правильно - т.е. рассматривать объекты как объекты.
Как некоторые метрики над объектами 1M:
struct/field: 50ms
class/property: 229ms
на основе следующего (разница в скорости в распределении объектов, а не в поле vs). Так что примерно в 5 раз медленнее, но все же очень, очень быстро. Поскольку это не будет вашим узким местом, преждевременно не оптимизируйте это!
using System;
using System.Collections.Generic;
using System.Diagnostics;
struct MyStruct
{
public int Id;
public string Name;
public DateTime DateOfBirth;
public string Comment;
}
class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public string Comment { get; set; }
}
static class Program
{
static void Main()
{
DateTime dob = DateTime.Today;
const int SIZE = 1000000;
Stopwatch watch = Stopwatch.StartNew();
List<MyStruct> s = new List<MyStruct>(SIZE);
for (int i = 0; i < SIZE; i++)
{
s.Add(new MyStruct { Comment = "abc", DateOfBirth = dob,
Id = 123, Name = "def" });
}
watch.Stop();
Console.WriteLine("struct/field: "
+ watch.ElapsedMilliseconds + "ms");
watch = Stopwatch.StartNew();
List<MyClass> c = new List<MyClass>(SIZE);
for (int i = 0; i < SIZE; i++)
{
c.Add(new MyClass { Comment = "abc", DateOfBirth = dob,
Id = 123, Name = "def" });
}
watch.Stop();
Console.WriteLine("class/property: "
+ watch.ElapsedMilliseconds + "ms");
Console.ReadLine();
}
}
Я могу только догадываться, почему они поддерживают только свойства: возможно, потому, что, как представляется, универсальное соглашение в платформе .NET никогда не выставляет изменчивые поля (, вероятно, для защиты бинарной совместимости ), и они каким-то образом ожидал, что все программисты будут следовать одному и тому же соглашению.
Кроме того, хотя поля и свойства доступны с одним и тем же синтаксисом, привязка данных использует отражение, и (поэтому я слышал) отражение должно использоваться по-разному для полей доступа чем для доступа к свойствам.