python命名空间,类成员,对象成员(代码片段)

bitcarmanlee bitcarmanlee     2023-03-03     133

关键词:

1.命名空间

关于python中的命名空间,可以先看官方文档里的一个说明

A namespace is a mapping from names to objects.Most namespaces are currently implemented as Python dictionaries。

1.namespace(命名空间)是从名称到对象的映射。
2.大部分的namespace目前都是通过python中的字典实现的。

命令空间为项目中提供了一种避免名字冲突的方法。不同命名空间之前是相互独立的,因此在同一个命名空间中不能重名,但是不同命名空间可以名字一样。

跟这情况很像的就是文件系统:如果把一个文件夹类比为命名空间,那么同一个文件夹中不能有相当名字的文件或者文件夹,但是不同文件夹中可以有相同名字的文件或者文件夹。

2.类命名空间与类对象命名空间

在python里,类与对象都有自己的命名空间,可以看如下例子。

class TestClass(object):
    class_value = 1

    def __init__(self, value):
        self.value = value

t = TestClass(10)
print(TestClass.__dict__)
print(t.__dict__)
'__module__': '__main__', 'class_value': 1, '__init__': <function TestClass.__init__ at 0x100955290>, '__dict__': <attribute '__dict__' of 'TestClass' objects>, '__weakref__': <attribute '__weakref__' of 'TestClass' objects>, '__doc__': None
'value': 10

可以通过__dict__访问类或者对象的命名空间。我们通过"."去访问对象的属性或者方法,其实就是去对象的命名空间找对应的名字。

当通过名字访问对象属性的时候,访问属性如下:
1.先从对象的命名空间寻找对应属性,如果找到对应属性,直接返回结果。
2.如果在对象的命名空间没有找到,则从类的命名空间继续寻找,找到了返回。
3.还找不到,抛异常。

class TestClass(object):
    class_value = 1

    def __init__(self, value):
        self.value = value


t = TestClass(10)
print(t.value)
print(t.class_value)
print(TestClass.class_value)

输出结果

10
1
1

通过上面的例子不难看出,类变量即可以被实例对象访问,也可以被类名直接访问。

3.类变量用途

可以用来定义常量

class Round(object):
    pi = 3.14

    def __init__(self, r):
        self.r = r

    def calc_area(self):
        return Round.pi * self.r * self.r


round = Round(2)
print(round.pi)
print(round.calc_area())

输出结果为

3.14
12.56

可以用来充当计数器

class Round(object):
    cur_count = 0
    max_count = 5

    def __init__(self):
        self.data = []

    def add_item(self, num):
        if len(self.data) >= Round.max_count:
            print("the data list is full!")
        else:
            self.data.append(num)
            Round.cur_count += 1


round = Round()
round.add_item(1)
round.add_item(2)
round.add_item(3)
print(round.cur_count)
round.add_item(4)
round.add_item(5)
print(round.cur_count)
round.add_item(6)
print(round.cur_count)
3
5
the data list is full!
5

还可以记录所有类对象

class Round(object):

    rs = []

    def __init__(self, r):
        self.r = r
        Round.rs.append(r)


r1 = Round(1)
r2 = Round(2)
r3 = Round(3)
print(Round.rs)
[1, 2, 3]

4.通过类对象无法给类变量赋值

class MyClass(object):

    class_value = 1

    def __init__(self, value):
        self.value = value


print("MyClass.class_value is: ", MyClass.class_value)
obj = MyClass(10)
print(obj.__dict__)
print("obj.class_value is: ", obj.class_value)
obj.class_value = 2
print(obj.__dict__)

print("obj.class_value is: ", obj.class_value)
print("MyClass.class_value is: ", MyClass.class_value)
print(MyClass.__dict__)
MyClass.class_value is:  1
'value': 10
obj.class_value is:  1
'value': 10, 'class_value': 2
obj.class_value is:  2
MyClass.class_value is:  1
'__module__': '__main__', 'class_value': 1, '__init__': <function MyClass.__init__ at 0x10114f290>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None

通过上面例子不难看出,obj.class_value = 2这句并不能直接改变类属性的值,而是给obj自己的命名空间中新添加了一个class_value变量,类空间中的class_value值仍为1。
总结起来就是:如果通过对象来给类变量赋值,将只会覆盖那个对象中的值,类变量的值并未发生改变。

5.可变属性

如果类命名空间中的属性是可变的,那么如果类实例改变了属性,类属性也会发生改变。

class MyClass(object):

    data = []

    def __init__(self, value):
        self.value = value

m1 = MyClass(111)
m2 = MyClass(222)
m1.data.append(1)
print(m1.data)
print(MyClass.data)
m2.data.append(2)
print(m2.data)
print(m1.data)
print(MyClass.data)
[1]
[1]
[1, 2]
[1, 2]
[1, 2]

所以如果类属性是可变类型,一定要引起高度注意。

6.对象成员变量的set/get方法实现

java代码里头,通常通过get/set的方式操作对象属性,python里面也可以通过property的方式实现。

class DefineError(object):

    def __init__(self, errors):
        self._errors = errors

    @property
    def errors(self):
        if self._errors is None:
            print("errors is None")

        return self._errors

    @errors.setter
    def errors(self, value):
        self._errors = value

也可以如下写法

class CustomizeError(object):

    def __init__(self, errors):
        self._errors = errors

    def _get_errors(self):
        return self._errors

    def _set_errors(self, value):
        self._errors = value

    errors = property(fget=_get_errors, fset=_set_errors)

需要注意的一点是,属性的方法名不能与实例变量名相同。

class DefineError(object):

    def __init__(self, errors):
        self.errors = errors

    @property
    def errors(self):
        if self.errors is None:
            print("errors is None")

        return self.errors

    @errors.setter
    def errors(self, value):
        self.errors = value

比如上面的代码,会报错。

......
  [Previous line repeated 993 more times]
RecursionError: maximum recursion depth exceeded

因为在调用obj.errors的时候,首先会转化为方法调用,会执行return self.errors这一行。这个时候会被视为属性调用,有转化为方法调用,最后就是一个死循环,然后抛出RecursionError的异常。

7.下划线的使用

单下划线:
_XX: 约定成员私有
XX_: 与python关键词区分

双下划线:
__XX: 避免子类重写
__XX__: 内置特殊成员


类的成员和命名空间(代码片段)

类的成员和命名空间classA:Country=‘中国‘#静态变量/静态属性存储在类的命名空间里的def__init__(self,name,age):#绑定方法存储在类的命名空间里的self.name=nameself.age=agedeffunc1(self):passdeffunc2(self):passclassA:Country=‘中国‘#静态变量/静态属... 查看详情

c++大纲及疑惑点三(代码片段)

...面向对象类的声明和对象的定义访问权限定义对象的方法命名规范类外定义成员函数并非所有成员函数必须公有类的成员函数访问权限的设定成员函数存储方式对象成员引用的方法通过对象名和成员运算符访问对象中的成员通过... 查看详情

在 C++ 中使用类的命名空间定义类的成员

】在C++中使用类的命名空间定义类的成员【英文标题】:Definemembersofaclassusingclass\'snamespaceinc++【发布时间】:2018-07-2620:21:41【问题描述】:我很少有名称很长的类以及它们的成员函数。在C++中,有一个技巧可以让您使用一个命名... 查看详情

c++类中的静态成员函数以及静态成员变量(代码片段)

...态的,称为静态成员。静态成员变量需要在类外分配空间,static成员变量是在初始化时分配内存的,程序结束时释放内存。静态成员函数只能访问静态成员函数和静态成员变量,没有this指针。静态成员是整个类共有的&... 查看详情

静态成员数据和静态成员函数(代码片段)

...类只是定义了其结构、类型,而创建对象时才会分配内存空间。比如一个Student类,其中有一个成员数据totalNumber,且由这个类创建了10个对象 查看详情

python全栈--9.1--面向对象进阶-super类对象成员--类属性-私有属性查找源码类对象步骤类特殊成员isinstanceissubclass异常处理(代码片段)

...向对象三大特性:封装、继承和多态 本篇将详细介绍Python类的成员 查看详情

类成员函数调用deletethis会发生什么呢?(代码片段)

...的内存模型。当一个类对象声明时,系统会为其分配内存空间。在类对象的内存空间中,只有数据成员和虚函数表指针,并不包含代码内容,类的成员函数单独放在代码段中。在调用成员函数时,隐含传递一个this指针,让成员... 查看详情

为啥我不能从不同命名空间中的朋友类更改类的私有成员?

】为啥我不能从不同命名空间中的朋友类更改类的私有成员?【英文标题】:Whycan\'tIchangeaprivatememberofaclassfromafriendclassinadifferentnamespace?为什么我不能从不同命名空间中的朋友类更改类的私有成员?【发布时间】:2011-05-1416:59:49... 查看详情

类和对象类的6个默认成员函数(代码片段)

...1.构造函数1.1无参构造函数1.2默认构造函数1.3成员变量的命名风格1.4构造函数的赋值1.5初始化列表2.析构函数3.拷贝构造函数4.运算符重载4.1赋值运算符5.const成员5.1const修饰类的成员函数总结前言本篇文章将带大家进一步了解C+&... 查看详情

123213(代码片段)

类空间大小计算类所占内存的大小是由成员变量(静态变量除外)决定的,成员函数(这是笼统的说,后面会细说)是不计算在内的。注意:成员函数还是以一般的函数一样的存在。a.fun()是通过fun(a.this)来调用的。所谓成员函数... 查看详情

c++|详解类成员指针:数据成员指针和成员函数指针及应用场合

...对于成员的调用,需要有类对象的限定,一方面是一个类命名空间,另一方面用于传递隐含的this指针。数据和函数,包括类对象的数据成员和成员函数,都是可以寻址的,自然也可以定义一个指针,使其指向类成员或成员函数... 查看详情

python面向对象和类成员和异常处理(代码片段)

python面向对象你把自己想象成一个上帝,你要创造一个星球,首先你要把它揉成一个个球,两个直径就能创造一个球 classstar:‘‘‘名字(name),赤道直径(equatorialdiameter),极直径(polardiameter)‘‘‘def__init__(self,name,eqDiameter,poDiam... 查看详情

类对象里面只有成员变量占用空间,成员函数不占用空间。

...的提问,可以这样理解:变量是什么?就是内存中的一块空间,可以放任何数字或字符在这个空间里(这和变量的定义有关,例如:字符型、整型等)。函数是什么?是实现一个特定功能的一段代码,这段代码是直接运行的(CPU... 查看详情

java13.静态类成员(代码片段)

...后分配的内存会一直存在,直到程序推出时才会释放内存空间。在java程序里,所有东西都是对象,而对象的抽象就是类,对于一个类而言,如果要使用他 查看详情

c++primer5th笔记(chap18大型程序工具)命名空间特性(代码片段)

1.命名空间成员定义在命名空间中的实体称为命名空间成员。在命名空间中定义的名字能够被命名空间中的其它成员直接訪问,命名空间外部的代码必须指出名字定义在哪个命名空间中命名空间中定义的成员可以直接使用名字࿰... 查看详情

js单例——如何避免通过命名空间访问类成员

】js单例——如何避免通过命名空间访问类成员【英文标题】:jssingleton-howtoavoidaccessingclassmembersviathenamespace【发布时间】:2011-12-3120:32:54【问题描述】:我正在尝试改进我的Javascript编码风格,并且一直在读到命名空间的东西很... 查看详情

14.11类的成员修饰符(代码片段)

...内部才能访问私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:init、call等)私有成员和公有成员的访问限制不同:静态字段:公有静态字段:类可以访问,类内部可以访问;派... 查看详情

python学习-面向对象2(代码片段)

类的成员类的成员可以分为三大类:字段、方法和属性所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段。而其他的成员,则都是保存在类中,即:无论对象的多少,在... 查看详情