什么是Python命名空间

时间:2010-10-12 09:30:05

标签: python programming-languages namespaces

我刚开始学习Python&在Python中遇到了“namespaces”概念。虽然我得到了它的概念,但我无法理解这个概念的严重性。

网上的一些浏览显示,违反PHP的原因之一是它没有对命名空间的原生支持。

有人可以解释如何使用名称空间&这个特性如何使编程更好(不仅仅是在Python中,因为我假设命名空间不是限于特定语言的概念)。

我主要来自Java和C编程背景。

6 个答案:

答案 0 :(得分:45)

命名空间是一种实现范围的方法。

在Java(或C)中,编译器通过静态范围分析确定变量的可见位置。

  • 在C中,范围是函数的主体,或者是全局的,或者是外部的。编译器会为您解释此问题,并根据范围规则解析每个变量名称。编译完所有模块后,链接器将解析外部名称。

  • 在Java中,范围是方法函数的主体,或类的所有方法。某些类名也具有模块级范围。同样,编译器在编译时计算出来并根据范围规则解析每个名称。

在Python中,每个包,模块,类,函数和方法函数都拥有一个“名称空间”,其中解析了变量名称。另外,如果名称不在本地名称空间中,则使用全局名称空间。

在本地命名空间(函数体,模块等)中检查每个变量名,然后在全局命名空间中进行检查。

变量通常仅在本地名称空间中创建。 globalnonlocal语句可以在本地名称空间之外创建变量。

当评估函数,方法函数,模块或包(即,开始执行)时,将创建命名空间。将其视为“评估背景”。当函数或方法函数等完成执行时,将删除命名空间。变量被删除。也可以删除对象。

答案 1 :(得分:5)

命名空间可以防止类,方法和对象之间发生冲突,这些冲突可能是由不同的人编写的。

来自Java背景,您可能熟悉如何使用包来实现这一目标,例如您可以创建一个movieyoda.DateUtils类,我可以创建一个mikej.DateUtils类,该包允许使用类来区分它们。 (Python有something very similar。)

在5.3.0中将命名空间添加到PHP中,但在早期版本(以及其他不提供命名空间的语言)中,您必须在类和方法名称前加上一些内容,以降低名称冲突的风险。例如一个movieyoda_parse_file函数。

答案 2 :(得分:3)

要了解名称空间,您还必须对Python中的模块有所了解。模块只是一个包含Python代码的文件。此代码可以是Python类,函数或仅列出名称的形式。每个模块都有自己的全局命名空间。因此,在同一模块中不能有两个类或两个函数,它们具有相同的名称,因为它们共享模块的命名空间。

参考:http://bytebaker.com/2008/07/30/python-namespaces/

答案 3 :(得分:0)

如果您与其他人一起制作大型节目,您可以根据需要编写自己的节目部分。文件中的所有变量都是私有的,不会发生冲突。 编写PHP程序时,很容易错误地重写全局变量。在python中,您可以根据需要导入其他模块变量,它们将在您的模块上“全局”。

您可以将一个文件视为Python中的一个对象。编写PHP程序时,可以通过使用实例变量编写类来实现相同的目的。

答案 4 :(得分:0)

我完成了S.Lott的答案。

我想说,命名空间是一种在范围内实现名称管理的方法,因为范围不仅仅是名称管理。

在C中,范围有4种类型:全局,函数,块和函数参数(原型)。根据需要,这些类型中的每一种都可以创建一个或多个名称空间。 C中有4 ns   - 标签为s / u / e   - 类型名称,函数名称和var名称的ID   - 函数原型内的参数   - s / u内的成员和位域。

与此类似,标签标识符和函数名称不会发生冲突,但typedef定义的类型名称可能会与变量名称冲突。

在python中有一个内置命名空间,它包含全局ns,全局ns由加载的模块提供。内置ns包含变量。变量的符号可以定义对象或函数 - 例如,+在那里定义。模块的全局ns持续到终止。

另请参阅that,当然还有that

答案 5 :(得分:0)

命名空间提供了一种管理范围内定义的标识符的方法。换句话说,它们用于将名称映射到值(或更精确地说,是对存储位置的引用)。

例如,在命名空间的上下文中,以下表达式

x = 10

会将标识符x与持有值10的对象的存储位置相关联。


在Python中,名称空间本质上有两种“类型”。 实例和类名称空间

实例命名空间在单个对象范围内管理名称和值之间的映射。另一方面,源代码中定义的每个类都有单独的类命名空间。这种类型的名称空间处理对象的所有实例共享的所有成员。


示例

现在考虑以下示例,其中为每个成员表示它属于类还是实例名称空间:

class Customer:

    def __init__(self, first_name, last_name, email): # __init__ -> Customer Class Namespace
        self._first_name = first_name # _first_name -> Instance Namespace
        self._last_name = last_name # _last_name -> Instance Namespace
        self._email = email # _email -> Instance Namespace

    def get_full_name(self): # Customer Class Namespace
        return f"{self._first_name} {self._last_name}"


class PremiumCustomer(Customer):

    PREMIUM_MEMBERSHIP_COST = 4.99  # PremiumCustomer Class Namespace


    class Subscription: # PremiumCustomer Class Namespace

        def __init__(self, customer_email): # Subscription Class Namespace
            self._customer_email = customer_email # Instance Namespace

    def __init__(self, first_name, last_name, email, card_number): # PremiumCustomer Class Namespace
        super().__init__(first_name, last_name, email)
        self._card_number = card_number # _card_number -> Instance Namespace

    def get_card_number(self): # PremiumCustomer Class Namespace
        return self._card_number