Why did Django 1.9 replace tuples () with lists []

2019-03-14 07:13发布

问题:

I am bit curious to know why Django 1.9 replaced tuples () with lists [] in settings, URLs and other configuration files

I just upgraded to Django 1.9 and noticed these changes. What is the logic behind them?

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles'
    ]

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

urls.py

urlpatterns = [
    url(r'^', admin.site.urls),
]

Is anything different because of these changes?

回答1:

It is explained in issue #8846 (emphasis mine):

In the documentation for ​Creating your own settings there's a recommendation which reads "For settings that are sequences, use tuples instead of lists. This is purely for performance."

This is bunk. Profiling shows that tuples run no faster than lists for most operations (certainly looping, which we are likely to do most often). On the other hand, list-literal syntax has the advantage that it doesn't collapse to a single value when you have a single item and omit the trailing comma, like tuple syntax. Using list syntax is no slower, more legible and less error prone. An often-expressed view in the wider Python community seems that tuples should not be considered as immutable lists. They are intended as fixed-length records - indeed the mathematical concept of a tuple is quite distinct from that of a sequence.

Also see this answer for a more up-to-date discussion.

Another answer (not directly related to this issue) demonstrates that accessing elements is actually faster with a list.

Update and further information: It is correct that the above issue was closed years ago, but I included it because it explained the rationale behind the decision and many similar discussions refer to the same ticket. The actual implementation decision was triggered after the following discussion on django-developers started by core Django developer Aymeric Augustin:

I prefer them [lists] for two reasons:

1) All these settings are sequences of similar things. Such values are best represented with lists, unless they have to be immutable, in which case a tuple can be used. (tuples are both “namedtuples without names” and “immutable lists” in Python.)

2) Lists aren’t prone to the “missing comma in single-item tuple” problem which bites beginners and experienced pythonistas alike. Django even has code to defend against this mistake for a handful of settings. Search for “tuple_settings” in the source.

And the switch to lists actually happened in issue #24149 which also referred to the above discussion.



回答2:

In the release notes of 1.9, there is:

Default settings that were tuples are now lists

The default settings in django.conf.global_settings were a combination of lists and tuples. All settings that were formerly tuples are now lists.

So it appears that it was just done for consistency. Both tuples and lists should work fine. If you use a tuple with 1 element, remember the comma (1,) because otherwise it's not a tuple but simply an expression in parens.

As for urlpatterns, those used to be defined using a patterns() function, but that was deprecated in Django 1.8, as a list of url instances works fine. As the function will be removed in the future, it shouldn't be used in new apps and projects.