Установить значение строки без присвоения ей типа str?

#python #string #setvalue

#python #строка #setvalue

Вопрос:

Я ищу способ задать значение строки без изменения типа строки.

 class testStr(str):
    myattr = ""

# this works fine.
t = testStr("testing")
t.myattr = "Yay!"
print "String value is: '"   t   "' and its attr is set to '"   t.myattr   "'"

# obviously once this is done the type of t goes back to str
# and I lose the value of .myattr
t = "whatever"
  

Если возможно, я бы хотел, чтобы myattr сохранял это значение, пока строке присваивается новое значение. Это не обязательно должно работать как t = «whatever», но я не хочу вручную копировать значения myattr и многое другое, если я добавлю больше переменных в класс testStr.

РЕДАКТИРОВАТЬ: Вот решение, к которому я в итоге пришел. Это удовлетворяет всем моим потребностям, я надеялся на что-то более элегантное, но тем не менее я доволен этим:

 class config:
    class ConfigItem(str):
        def __init__(self, value):
            super( str, self ).__init__()
            self.var1 = "defaultv1"
            self.var2 = "defaultv2"

    def __init__(self):
        self.configTree = {}

    def __getitem__(self, key):
        if ( self.configTree.has_key(key) ): 
            return self.configTree[key]
        return ""

    def __setitem__(self, key, value):
        if ( value.__class__.__name__ == "ConfigItem" ):
            self.configTree[key] = value
            return

        if ( value.__class__.__name__ == "str" ):
            item = None
            if ( self.configTree.has_key(key) ): 
                item = self.configTree[key]
                new_item = self.ConfigItem(value)
                for attr in item.__dict__:
                    new_item.__setattr__(attr, item.__getattribute__(attr))
                self.configTree[key] = new_item
            else: 
                item = self.ConfigItem(value)
                self.configTree[key] = item

# test it out
cfg = config()
cfg["test_config_item"] = "it didn't work."

cfg["test_config_item"].var1 = "it worked!"
cfg["test_config_item"] = "it worked!"
print cfg["test_config_item"]
print cfg["test_config_item"].var1
  

Это позволяет использовать параметр конфигурации в виде строки, однако он по-прежнему содержит дополнительную информацию, если это было необходимо.

Комментарии:

1. Переменные Python не являются переменными в смысле C / C .

Ответ №1:

Оператор t = "whatever" не «изменяет значение, содержащееся в t «, а скорее повторно привязывает t к другому объекту. Если вы хотите изменить t , то вместо этого вы должны изменить его с помощью атрибута, либо присвоив атрибуту, либо вызвав метод.

Комментарии:

1. Я готов использовать метод для установки значения строки. Я просто не хотел выполнять ‘newt.myattr = oldt.myattr’ для перемещения по значению каждой переменной, потому что тогда мне придется обновлять функцию, чтобы делать это для каждого атрибута, который я добавляю в класс. Я надеялся на что-то более элегантное.

Ответ №2:

Проблема (с которой вы разобрались) заключается в том, что t присваивается новому объекту типа str, у которого нет myattr .

Я думаю, что самым простым способом сделать это было бы просто создать класс, который не наследуется от str, но содержит элемент string, а также ‘myattr’

Комментарии:

1. Я думаю, на что я действительно надеялся, так это на то, что класс str содержал внутреннюю функцию для изменения значения или переменной, которая содержала это значение ( я надеялся на __ value __ или что-то в этом роде)

2. Если вы хотите, чтобы объект имел строковое значение, тогда определите методы __str__() и / или __unicode__() .

3. @python5000 — Фактический буфер базовых символов не отображается, см. svn.pythonmac.org/python24/python24-fat/Include/unicodeobject.h если вам интересно @Ignacio — я думаю, он хочет установить это, а не иметь строковое значение

4. Строки Python неизменяемы, так что вам не повезло. У меня есть похожий класс, который присоединяет кортеж к строке, но мне никогда не нужно было заменять строку. Единственное, что меня беспокоит, это то, что запись t = "test" strtuple("test2", 1, 2) приводит к простому, str потому что str.__add__ оператор отбрасывает кортеж. t = strtuple("test", 1, 2) "test2" тем не менее, это работает.

Ответ №3:

Вы могли бы рассмотреть этот подход. Кажется, это обеспечивает функциональность, которую вы ищете.

 class testStr(object):
    def __init__(self, string, myattr = ""):
        self.string = string
        self.myattr = myattr
  

Запускаю те же тестовые примеры, что вы показали.

 >>> from testStr import testStr
>>> t = testStr('testing')
>>> t.string
'testing'
>>> t.myattr = 'Yay!'
>>> t.myattr
'Yay!'
>>> t.string = 'whatever'
>>> t.string
'whatever'
>>> t.myattr
'Yay!'
  

Или, если вы действительно хотите наследовать от str (но это действительно менее питоническое и также не решает вашу проблему):

 class testStr(str):
    def __init__(self, string, myattr = ""):
        super(testStr, self).__init__(string)
        self.myattr = myattr
  

Комментарии:

1. Да, именно так все и началось. У меня было именно то, что вы описали, однако теперь моя цель в жизни — создать версию, в которой вы все еще можете печатать t и получать «ура!» и по-прежнему получать доступ к .myattr, даже если мне нужно создать функцию t.setValue («что угодно»).

2. @python5000 Ты имеешь в виду, напечатать t и получить ‘testing’? Зачем вам это нужно делать? Что не так с установкой t.string, t.myattr и расширением по мере необходимости? Вы всегда можете создать t.setValue(‘whatever’), чтобы он изменял self.string и оставлял myattr в покое.

Ответ №4:

Почему вы не используете кортеж или список?

 >>> s = [ ["the string", 15], ["second string", 12] ]
>>> print s
[['the string', 15], ['second string', 12]]

>>> s[0][1] = 8;
>>> print s
[['the string', 8], ['second string', 12]]

>>> print s[0]
['the string', 8]

>>> print s[1]
['second string', 12]