精华内容
下载资源
问答
  • Python中的可变对象和不可变对象

    千次阅读 2017-12-11 10:25:31
    Python在heap中分配的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容是可变的,例如list。而可变的对象则相反,表示其内容可变。不可变对象:int,string,float,tuple 可变对象 :l

    python变量赋值(可变与不可变)

    知识点:python中,万物皆对象。
         python中不存在所谓的传值调用,一切传递的都是对象的引用,也可以认为是传址。
    Python在heap中分配的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容是可变的,例如list。而不可变的对象则相反,表示其内容不可变。

    不可变对象:int,string,float,tuple
    可变对象 :list,dictionary
    一、不可变对象

    由于Python中的变量存放的是对象引用,所以对于不可变对象而言,尽管对象本身不可变,但变量的对象引用是可变的。运用这样的机制,有时候会让人产生糊涂,似乎可变对象变化了。如下面的代码:

    i=73
    i=i+2
    不可变对象不变,引用变了
    这里写图片描述

    不可变的对象的特征没有变,依然是不可变对象,变的只是创建了新对象,改变了变量的对象引用。
    看看下面的代码,更能体现这点的。

    print(id(100)) # 1362346144
    a = 100
    print(id(a)) # 1362346144
    b = 100
    print(id(b)) # 1362346144
    但如果变成258则id就有变化

    print(id(258)) # 1659053321968
    a = 258
    print(id(a)) # 1659053321968
    b = 258
    print(id(b)) # 1659053319280
    为何不一样了?

    (答案转自知乎问题:为什么Python有相同的不可变对象id不同?或者知乎原答案)

    二、可变对象
    这里写图片描述
    其对象的内容是可以变化的。当对象的内容发生变化时,变量的对象引用是不会变化的。

    关于此问题的大坑:函数默认参数的使用
    先定义一个函数,传入一个list,添加一个END再返回:
    def add_end(L=[]):
    L.append(‘END’)
    return L
    当你正常调用时,结果似乎不错:

    >>> add_end([1, 2, 3])
    [1, 2, 3, 'END']
    >>> add_end(['x', 'y', 'z'])
    ['x', 'y', 'z', 'END']

    当你使用默认参数调用时,一开始结果也是对的:

    >>> add_end()
    ['END']

    但是,再次调用add_end()时,结果就不对了:

    >>> add_end()
    ['END', 'END']
    >>> add_end()
    ['END', 'END', 'END']

    很多初学者很疑惑,默认参数是[],但是函数似乎每次都“记住了”上次添加了’END’后的list。
    原因解释如下:
    Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。
    所以,定义默认参数要牢记一点:默认参数必须指向不变对象!
    要修改上面的例子,我们可以用None这个不变对象来实现:

    def add_end(L=None):
        if L is None:
            L = []
        L.append('END')
        return L

    现在,无论调用多少次,都不会有问题:

    >>> add_end()
    ['END']
    >>> add_end()
    ['END']

    为什么要设计str、None这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。

    作者:五秋木
    链接:http://www.jianshu.com/p/b690422ec02a
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    展开全文
  • Python中可变对象和不可变对象

    千次阅读 2017-02-13 12:56:21
    之前写了FPGrowth的代码,写得非常恶心,觉得C语言、C++的工程文件很相同。其中就有关于传引用、传值的疑问。截一段Leetcode的代码这题好像是Leetcode ...经过查看资料我就知道这命名域以及可变对象和不可变对象

    之前写了FPGrowth的代码,写得非常恶心,觉得和C语言、C++的工程文件很不相同。其中就有关于传引用、传值的疑问。

    截一段Leetcode的代码

    这里写图片描述

    这题好像是Leetcode 93附近的一道 获得二叉树最大深度的题目。

    我使用了dfs,本来以为python是传对象引用的,所以在dfs中更新了ans,那么返回的ans也会改变,但是最后得到的结果保持1。

    经过查看资料我就知道这和命名域以及可变对象和不可变对象有关。

    那么我们来说一说可变对象和不可变对象。

    列表

    先看下面的例子:

    >>> l = [1, 2, 3]
    >>> ll = l
    >>> ll.remove(1)
    >>> l
    [2, 3]
    >>> 
    >>>a = [1]
    >>>b = a 
    >>>b[0] = 2
    >>>a
    [2]
    >>> l = [1, 2, 3]
    >>> ll = l[:]
    >>> ll.remove(1)
    >>> l
    [1, 2, 3]
    >>>

    列表是可变对象类型,因此传递的时候,变量名b绑定的内存地址与a绑定的内存地址是同一地址。

    我们可以看到,在第一个例子中,我们更改了ll的同时,l也更改了。这是因为我们的复制是浅复制,lll指向同一个对象。

    第二个例子是通过便遍历来赋值,则变为深复制。

    这和copy中的copy、deepcopy类似。

    数值

    >>> x = 1
    >>> y = 1
    >>> x is y
    True
    >>>id(x) == id(y)
    False

    数值为不可变类型,x与y指向的是数值为1的同一内存地址。

    对于类来说也是如此:

    class b:
        x = []
        def set(self):
            self.x.append(1)
        def get(self):
            return self.x
    
    for i in range(3):
        a = b()
        print b.__dict__
        a.set()
        print a.get()
    
    '''
    {'x': [], '__module__': '__main__', 'set': <function set at 0x7f89a319bcf8>, '__doc__': None, 'get': <function get at 0x7f89a319bd70>}
    [1]
    {'x': [1], '__module__': '__main__', 'set': <function set at 0x7f89a319bcf8>, '__doc__': None, 'get': <function get at 0x7f89a319bd70>}
    [1, 1]
    {'x': [1, 1], '__module__': '__main__', 'set': <function set at 0x7f89a319bcf8>, '__doc__': None, 'get': <function get at 0x7f89a319bd70>}
    [1, 1, 1]
    '''

    python中,万物皆对象。python中不存在所谓的传值调用,一切传递的都是对象的引用,也可以认为是传址。

    python中,对象分为可变(mutable)和不可变(immutable)两种类型。

    元组(tuple)、数值型(number)、字符串(string)均为不可变对象,而字典型(dictionary)和列表型(list)的对象是可变对象。

    >>>a = 1 #将名字a与内存中值为1的内存绑定在一起
    >>>a = 2 #将名字a与内存中值为2的内存绑定在一起,而不是修改原来a绑定的内存中的值,这时,内存中值为1的内存地址引用计数-1,当引用计数为0时,内存地址被回收
    >>>b = a #变量b执行与a绑定的内存
    >>>b = 3 #创建一个内存值为3的内存地址与变量名字b进行绑定。这是a还是指向值为2的内存地址。
    >>>a,b
    >>>(2,3)
    展开全文
  • (转)Java 可变对象和不可变对象

    千次阅读 2018-07-23 15:44:18
     不可变对象(Immutable Objects)即对象一旦被创建它的状态(对象的数据,也即对象属性值)就能改变,反之即为可变对象(Mutable Objects)。  不可变对象的类即为可变类(Immutable Class)。Java平台类库中包含...

    一、简单定义
      不可变对象(Immutable Objects)即对象一旦被创建它的状态(对象的数据,也即对象属性值)就不能改变,反之即为可变对象(Mutable Objects)。
      不可变对象的类即为不可变类(Immutable Class)。Java平台类库中包含许多不可变类,如String、基本类型的包装类、BigInteger和BigDecimal等。

    二、优缺点
      不可变对象有很多优点:
      构造、测试和使用都很简单
      线程安全且没有同步问题,不需要担心数据会被其它线程修改
      当用作类的属性时不需要保护性拷贝
      可以很好的用作Map键值和Set元素
      不可变对象最大的缺点就是创建对象的开销,因为每一步操作都会产生一个新的对象。

    三、编写不可变类

      可以遵照以下几点来编写一个不可变类:
      确保类不能被继承 - 将类声明为final, 或者使用静态工厂并声明构造器为private
      声明属性为private 和 final
      不要提供任何可以修改对象状态的方法 - 不仅仅是set方法, 还有任何其它可以改变状态的方法
      如果类有任何可变对象属性, 那么当它们在类和类的调用者间传递的时候必须被保护性拷贝

    import java.util.Date;
    /**
     * Planet是一个不可变类,因为当它构造完成之后没有办法改变它的状态
     */
    public final class Planet {
        /**
         * 声明为final的基本类型数据总是不可变的
         */
        private final double fMass;
        /**
         * 不可变的对象属性 (String对象不可变)
         */
        private final String fName;
        /**
         * 可变的对象属性. 在这种情况下, 这个可变属性只能被这个类改变。
         * (在其它情况下, 允许在原生类外部改变一个属性是很有意义的;
         * 这种情况就是当属性作为其它地方创建的一个对象引用)
         */
        private final Date fDateOfDiscovery;
        public Planet(double aMass, String aName, Date aDateOfDiscovery) {
            fMass = aMass;
            fName = aName;
            //创建aDateOfDiscovery的一个私有拷贝
            //这是保持fDateOfDiscovery属性为private的唯一方式, 并且保护这个
            //类不受调用者对于原始aDateOfDiscovery对象所做任何改变的影响
            fDateOfDiscovery = new Date(aDateOfDiscovery.getTime());
        }
        /**
         * 返回一个基本类型值.
         *
         * 调用者可以随意改变返回值,但是不会影响类内部。
         */
        public double getMass() {
            return fMass;
        }
        /**
         * 返回一个不可变对象
         *
         * 调用者得到内部属性的一个直接引用. 由于String是不可变的所以没什么影响
         */
        public String getName() {
            return fName;
        }
    // /**
    // * 返回一个可变对象 - 不是一个好的方式.
    // *
    // * 调用者得到内部属性的一个直接引用. 这通常很危险,因为Date对象既可以
    // * 被这个类改变也可以被它的调用者改变.即,类不再对fDate拥有绝对的控制。
    // */
    // public Date getDateOfDiscovery() {
    // return fDateOfDiscovery;
    // }
        /**
         * 返回一个可变对象 - 好的方式.
         *
         * 返回属性的一个保护性拷贝.调用者可以任意改变返回的Date对象,但是不会
         * 影响类的内部.为什么? 因为它们没有fDate的一个引用. 更准确的说, 它们
         * 使用的是和fDate有着相同数据的另一个Date对象
         */
        public Date getDateOfDiscovery() {
            return new Date(fDateOfDiscovery.getTime());
        }
        /**
         * 测试方法
         * @param args
         */
        public static void main(String[] args) {
            Planet planet = new Planet(1.0D, "earth", new Date());
            Date date = planet.getDateOfDiscovery();
            date.setTime(111111111L);
            System.out.println("the value of fDateOfDiscovery of internal class : " + planet.fDateOfDiscovery.getTime());
            System.out.println("the value of date after change its value : " + date.getTime());
        }
    

    运行结果如下:

    the value of fDateOfDiscovery of internal class : 1393943752205
    the value of date after change its value : 111111111

      由此可见Planet类的属性fDateOfDiscovery在对象构造完成之后就没有再改变。
      在《Effective Java》一书中, Joshua Bloch提出了一个强制性的建议 :
      “类应该是不可变的,除非有很好的理由让它是可变的….如果一个类不能设计为不可变的,也要尽可能的限制它的可变性.”
      BigDecimal从技术上讲不是不可变的, 因为它没有声明为final.

    四、使用场景
      不可变类最适合表示抽象数据类型(如数字、枚举类型或颜色)的值。Java 类库中的基本数据类型的包装类(如Integer 、 Long 和 Float )都是不可变的,其它数字类型(如 BigInteger 和 BigDecimal )也是不可变的。表示复数或任意精度的有理数的类将比较适合设计为不可变类。甚至包含许多离散值的抽象类型(如向量或矩阵)也很适合设计成不可变类,这取决于你的应用程序。
      另一个适合用不可变类实现的好示例就是 事件 。事件的生命期较短,而且常常会在创建它们的线程之外的线程中消耗,所以使它们成为不可变的是利大于弊。大多数 AWT 事件类都没有 严格的 作为不可变类来实现。同样地,在 通信系统的 组件间 进行 消息传递,将消息对象设计成不可变的是明智的。

    五、参考资料

      《Effective Java》
      http://www.ibm.com/developerworks/library/j-jtp02183/
      http://www.javapractices.com/topic/TopicAction.do?Id=29
      http://www.javaworld.com/article/2077362/core-java/mutable-or-immutable.html
      http://www.javalobby.org/articles/immutable/

    转自:https://my.oschina.net/jackieyeah/blog/205198?fromerr=yJ78hGIV

    展开全文
  • Python在heap中分配的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容可变,而不可变对象是指对象内容可变。 可变(immutable):int、 字符串(string)、float、(数值型number)、 ...

    知识点:python中,万物皆对象。

       python中不存在所谓的传值调用,一切传递的都是对象的引用,也可以认为是传址。

    一、可变对象和不可变对象

    Python在heap中分配的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容可变,而不可变对象是指对象内容不可变。

    不可变(immutable):int、字符串(string)、float、(数值型number)、元组(tuple)

    可变(mutable):字典型(dictionary)、列表型(list)

    不可变类型特点:

      看下面的例子(例1)

    i = 73
    i += 2

    从上图可知,不可变对象的特征没有变,变的只是创建了新对象,改变了变量的对象引用。

      看一个例子(例2)

    >>>x = 1
    >>>y = 1
    >>>x = 1
    >>> x is y
    True
    >>>y is z
    True

      如上所示,因为整数为不可变,x,y,z在内存中均指向一个值为1的内存地址,也就是说,x,y,z均指向的是同一个地址,值得注意的是,整形来说,目前仅支持(-1,100)。

      总结一下,不可变对象的优缺点。

        优点是,这样可以减少重复的值对内存空间的占用

        缺点呢,如例1所示,我要修改这个变量绑定的值,如果内存中没用存在该值的内存块,那么必须重新开辟一块内存,把新地址与变量名绑定。而不是修改变量原来指向的内存块的值,这回给执行效率带来一定的降低。

      下面看一个可变对象的例子(例3)

    m=[5,9]
    m+=[6]
    

    二、函数参数:

    Python函数参数对于可变对象,函数内对参数的改变会影响到原始对象;对于不可变对象,函数内对参数的改变不会影响到原始参数。原因在于:

    1、可变对象,参数改变的是可变对象,其内容可以被修改。

    2、不可变对象,改变的是函数内变量的指向对象。


    参考链接:

    http://www.cnblogs.com/evening/archive/2012/04/11/2442788.html

    http://thomaschen2011.iteye.com/blog/1441254


    展开全文
  • java中可变对象不可变对象

    千次阅读 2017-03-17 16:11:10
    可变对象(mutable Objects),不可变对象(Immutable ojbects),那么他们有什么区别呢? 不可变对象意味着这个对象是final的,对象中...可变对象和不可变对象相反,java中大部分都是可变对象不可变对象有哪些 Str
  • python精讲 不可变对象可变对象

    千次阅读 2020-07-22 15:46:35
    文章目录对象可变对象与不可变对象可变对象不可变对象 对象 Python 中的变量不是装有对象的“容器”,而是贴在对象上的“标签”。 真正的存贮位置是内存中 在python中,可变对象包括:list、set、dict、自定义对象...
  • JAVA - 可变对象不可变对象

    千次阅读 2018-06-14 18:34:08
    不可变对象在并发程序中比较有用,由于其状态无法改变,因此无法被线程的干扰损坏或者被视为一致状态。基本概念 *不可变对象(Immutable Objects)即对象一旦被创建它的状态(对象的数据,也即对象属性值)就能...
  • python中有可变对象和不可变对象可变对象:list,dict.不可变对象有:int,string,float,tuple.最近看到这些知识下面来整理一下... python不可变对象int,string,float,tuple先来看一个例子 def int_test(): i = 77...
  • 可变对象 vs 不可变对象(Python)

    千次阅读 2016-08-27 22:27:57
    Python 在 heap 中分配的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容是可变的,例如 list。而可变的对象则相反,表示其内容可变。 不可变对象:int,string,float,tuple 可变对象 :...
  • 可变对象不可变对象

    万次阅读 2018-08-12 22:22:48
    ”中,因为在调用方法时与方法内部,输出id是相同,所以能理解官方的那句话 Remember that arguments are passed by assignment in Python.&nbsp; 要记住,Python 里的参数是通过赋值传递的。  之后...
  • python中的可变对象不可变对象

    千次阅读 2018-12-20 22:40:20
    python与C/C++一样,它的变量使用有自己的特点,...下面本文将对python里面的“可变数据类型”不可变数据类型”进行分析。 首先,我们需要知道在python中哪些是可变数据类型,哪些是不可变数据类型。可变数据...
  • java 中不可变对象

    千次阅读 2018-11-30 23:12:07
    本文我们说明什么是不可变对象,在java 中如何实现以及其有好处。 1. 什么是不可变对象 不可变对象是指对象被创建之后,其内部状态保存不变的对象。这意味着其公开的API保证在对象的整个生命周期中其行为保持...
  • Java不可变对象

    千次阅读 2017-01-12 13:45:46
    一、不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就能改变其成员变量值。...说完可变和不可变类的区别,我们需要进一步了解为什么要有不可变类?这样的特性对JAVA
  • 文章目录四个线程安全策略不可变对象定义不可变对象需要满足的条件如何创建不可变对象使用final关键字定义不可变对象修饰变量示例final 修饰基本数据类型及String: 初始化之后能修改 (线程安全)final修饰引用...
  • 深入理解Java中的不可变对象

    千次阅读 2020-03-20 10:49:23
    二哥,你能给我说说为什么 String 是 immutable 类(不可变对象)吗?我想研究它,想知道为什么它就可变了,这种强烈的愿望就像想研究浩瀚的星空一样。但无奈自身功力有限,始终觉得雾里看花终隔一层。二哥你的...
  • 不可变对象和

    千次阅读 2014-11-20 18:58:41
    要使一个类成为一个不可变类,必须满足下面的需求 1.所有的数据域都是私有的; 2.没有修改器方法; 3.没有一个访问器访问,它会返回一个指向可变数据域的已用 例: public class student{ private...
  • 周六写一篇关于python 的博客(可变 :地址传递 不可变:值传递)

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,064,985
精华内容 425,994
关键字:

可变对象和不可变对象