IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python命名空间,类成员,对象成员 -> 正文阅读

[Python知识库]python命名空间,类成员,对象成员

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__: 内置特殊成员


  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-12-23 15:43:22  更:2021-12-23 15:43:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 4:34:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码