您的位置:澳门402永利com > 编程应用 > 及单向队列,Python技术员无人问津但你应有明白

及单向队列,Python技术员无人问津但你应有明白

发布时间:2019-09-23 20:45编辑:编程应用浏览(113)

      刚刚开始学习c++。之前c的内容掌握的也不多,基本只是一本概论课的程度,以前使用c的struct写过的链表、用python写过简单的数据结构,就试着把两者用c++写出来,也是对c++的class,以及继承中的public/protected/private的性质进行初步了解。第一次写头文件.h和源文件.cpp分开的c++代码。过程中参考了ProLyn和kgvito的代码,基本就是百度“单链表 c++”的前几个搜索结果。

    一、不要使用可变对象作为函数默认值

      节点listNode还是用struct来写了,因为我想节点除了构造没有什么方法需要实现,变量和构造也总是需要处于public的状态方便其他类函数调用。

    复制代码 代码如下:

      栈是保持先进后出(First In Last Out, 或者FILO)的数据结构,在这里只是定义了最基本的五种方法,实现从尾部添加、从尾部弹出;队列是保持先进先出(First In First Out, FIFO)的数据结构,同样定义了最基本的方法实现从尾部添加从头部弹出。二者我都使用了private继承,因为除了重新封装list的几种方法外,多数list的方法都不需要出现在这两种数据结构中,我认为禁止public访问这些方法比较好。

    In [1]: def append_to_list(value, def_list=[]):
       ...:         def_list.append(value)
       ...:         return def_list
       ...:

     1 // linked_list.h 2 // Base class linked list "linkList", derived "linkStack" & "linkQueue"  3 typedef int DataType; 4  5 // constructing struct "listNode" 6 struct listNode 7 { 8     DataType nodeVal; 9     listNode* nextNode;10     listNode(const DataType x);            // listNode construct func11 };12 13 // constructing base class "linklist"14 class linkList15 {16 private:                                // private variables headNode & tailNode17     listNode* headNode;18     listNode* tailNode;19 // construction functions, and operator overload20 public:21     linkList();22     linkList(const linkList& lista);23     linkList& operator=(linkList& lista);24     DataType operator[](int index);25 // other functions, public26 public:27     bool isEmpty();28     void PrintList();29     void PushBack(const DataType& x);30     void PushFront(const DataType& x);31     void PopBack();32     void PopFront();33     DataType PeekBack();34     DataType PeekFront();35     void InsertNext(listNode* pos, DataType x);36     void DeleteNext(listNode* pos);37     void Delete(listNode* pos);38     void Clear();39     void Remove(DataType x);40     void RemoveAll(DataType x);41     void Sort();42     int GetLength();43     listNode* Find(DataType x);44 };45 46 // derived class linkStack47 class linkStack : private linkList48 {49 public:50     linkStack();51     linkStack(const linkStack& stack1);52     linkStack& operator=(linkStack& stack1);53 // the least functions needed54 public:55     bool isEmpty();56     int getSize();57     void PushBack(const DataType& x);58     void PopBack();59     DataType PeekBack();60 };61 62 // derived class linkQueue63 class linkQueue : private linkList64 {65 public:66     linkQueue();67     linkQueue(const linkQueue& queue1);68     linkQueue& operator=(linkQueue& queue1);69 70 public:71     bool isEmpty();72     int getSize();73     void PushBack(const DataType& x);74     void PopFront();75     DataType PeekFront();76 }
    

    In [2]: my_list = append_to_list(1)

      对struct listNode,class linkList, linkStack, linkQueue的方法的具体实现,后两者基本只是对于linkList的重新封装,为了能在private继承的子类中实现,也不得不在linkList中添加了一些没什么用处的函数。其中构造函数和赋值下标运算重载的写法都是现学的…如果现学的不到位请不吝赐教!

    In [3]: my_list
    Out[3]: [1]

      1 #include <iostream>  2 #include "linked_list.h"  3 using namespace std;  4 // construction func for listNode  5 listNode::listNode(const DataType x)  6     :nodeVal, nextNode  7 {}  8 // construction funcs for linkList  9 linkList::linkList()                        // without argument 10     : headNode, tailNode 11 {} 12  13 linkList::linkList(const linkList& lista)    // with argument 14     : headNode, tailNode 15 { 16     if (lista.headNode) { 17         listNode* tmp = lista.headNode; 18         while (tmp->nextNode) { 19             PushBack(tmp->nodeVal); 20             tmp = tmp->nextNode; 21         } 22         PushBack(tmp->nodeVal); 23     } 24 } 25 // operator reload = 26 linkList& linkList::operator=(linkList &lista) { 27     if (this != &lista) { 28         swap(headNode, lista.headNode); 29         swap(tailNode, lista.tailNode); 30     } 31     return *this; 32 } 33 // operator reload [] 34 DataType linkList::operator[](int index) { 35     if (index < 0 || headNode == nullptr) { 36         cout << "Invalid index!" << endl; 37         return -1; 38     } 39     else { 40         listNode* tmp = headNode; 41         int i; 42         while (tmp != nullptr && i < index) { 43             tmp = tmp->nextNode; 44             i++; 45         } 46         if (tmp == nullptr) { 47             cout << "Invalid index!" << endl; 48             return -1; 49         } 50         else { 51             return tmp->nodeVal; 52         } 53     } 54 } 55  56 bool linkList::isEmpty() { 57     if  { 58         return true; 59     } 60     else { 61         return false; 62     } 63 } 64  65 int linkList::GetLength() { 66     int count = 0; 67     listNode* tmp = headNode; 68     while  { 69         count++; 70         tmp = tmp->nextNode; 71     } 72     return count; 73 } 74  75 void linkList::PrintList() { 76     listNode* tmp = headNode; 77     if  { 78         cout << tmp->nodeVal; 79         tmp = tmp->nextNode; 80         while  { 81             cout << "->" << tmp->nodeVal; 82             tmp = tmp->nextNode; 83         } 84         cout << endl; 85     } 86     else { 87         cout << "Empty linked list!" << endl; 88     } 89 } 90  91 void linkList::PushBack(const DataType& x) { 92     if  { 93         tailNode->nextNode = new listNode; 94         tailNode = tailNode->nextNode; 95     } 96     else { 97         headNode = new listNode; 98         tailNode = headNode; 99     }100 }101 102 void linkList::PushFront(const DataType& x) {103     if  {104         listNode* tmp = new listNode;105         tmp->nextNode = headNode;106         headNode = tmp;107     }108     else {109         headNode = new listNode;110         tailNode = headNode;111     }112 }113 114 void linkList::PopBack() {115     if  {116         if (headNode->nextNode) {117             listNode* tmp = headNode;118             while (tmp->nextNode != tailNode) {119                 tmp = tmp->nextNode;120             }121             delete tailNode;122             tmp->nextNode = nullptr;123             tailNode = tmp;124         }125         else {126             delete headNode;127             headNode = nullptr;128             tailNode = nullptr;129         }130     }131     else {132         cout << "Empty linked list!" << endl;133     }134 }135 136 void linkList::PopFront() {137     if  {138         if (headNode->nextNode) {139             listNode* tmp = headNode->nextNode;140             delete headNode;141             headNode = tmp;142         }143         else {144             delete headNode;145             headNode = nullptr;146             tailNode = nullptr;147         }148     }149     else {150         cout << "Empty linked list!" << endl;151     }152 }153 154 DataType linkList::PeekBack() {155     if  {156         return tailNode->nodeVal;157     }158     else {159         cout << "Empty linked list!" << endl;160         return -1;161     }162 }163 164 DataType linkList::PeekFront() {165     if  {166         return headNode->nodeVal;167     }168     else {169         cout << "Empty linked list!" << endl;170         return -1;171     }172 }173 174 listNode* linkList::Find(DataType x) {175     listNode* targetNode = headNode;176     while (targetNode) {177         if (targetNode->nodeVal == x) {break;}178     }179     return targetNode;180 }181 182 void linkList::InsertNext(listNode* pos, DataType x) {183     if  {184         if (pos == tailNode) {185             listNode* tmp = new listNode;186             pos->nextNode = tmp;187             tailNode = tmp;188         }189         else {190             listNode* tmp = new listNode;191             tmp->nextNode = pos->nextNode;192             pos->nextNode = tmp;193         }194     }195     else {196         cout << "Invalid position!" << endl;197     }198 }199 200 void linkList::DeleteNext(listNode* pos) {201     if  {202         if (pos == tailNode) {203             cout << "Invalid node!" << endl;204         }205         else {206             listNode* tmp = (pos->nextNode)->nextNode;207             delete pos->nextNode;208             pos->nextNode = tmp;209         }210     }211     else {212         cout << "Invalid node!" << endl;213     }214 }215 216 void linkList::Remove(DataType x) {217     if  {218         if (headNode->nextNode) {219             listNode* tmp = headNode;220             while (tmp->nextNode) {221                 if ((tmp->nextNode)->nodeVal == x) {222                     DeleteNext;223                     break;224                 }225                 tmp = tmp->nextNode;226             }227         }228         else {229             if (headNode->nodeVal == x) {PopFront();}230         }231     }232 }233 234 void linkList::RemoveAll(DataType x) {235     if  {236         listNode* tmp = headNode;237         while (tmp->nextNode) {238             if ((tmp->nextNode)->nodeVal == x) {239                 if (tmp->nextNode == tailNode){240                     PopBack();241                     break;242                 }243                 else {DeleteNext;}244             }245             tmp = tmp->nextNode;246         }247         if (tmp->nodeVal == x) {248             PopBack();249         }250     }251 }252 253 void linkList::Clear() {254     if  {255         listNode* prev = headNode;256         listNode* tmp;257         while (prev->nextNode) {258             tmp = prev->nextNode;259             delete prev;260             prev = tmp;261         }262         headNode = nullptr;263         tailNode = nullptr;264     }265 }266 // construction funcs for linkStack267 linkStack::linkStack()                            // without arguments268     :linkList()269 {}270 271 linkStack::linkStack(const linkStack& stack1)    // with an argument272     :linkList273 {}274 // other public funcs for linkStack275 bool linkStack::isEmpty() {276     return linkList::isEmpty();277 }278 279 int linkStack::getSize() {280     return linkList::GetLength();281 }282 283 void linkStack::PushBack(const DataType& x) {284     linkList::PushBack;285 }286 287 void linkStack::PopBack() {288     linkList::PopBack();289 }290 291 DataType linkStack::PeekBack() {292     return linkList::PeekBack();293 }294 // construction funcs for linkQueue295 linkQueue::linkQueue()296     :linkList()297 {}298 299 linkQueue::linkQueue(const linkQueue& queue1)300     :linkList301 {}302 // other public funcs for linkQueue303 bool linkQueue::isEmpty() {304     return linkList::isEmpty();305 }306 307 int linkQueue::getSize() {308     return linkList::GetLength();309 }310 311 void linkQueue::PushBack(const DataType& x) {312     linkList::PushBack;313 }314 315 void linkQueue::PopFront() {316     linkList::PopFront();317 }318 319 DataType linkQueue::PeekFront() {320     return linkList::PeekFront();321 }
    

    In [4]: my_other_list = append_to_list(2)

      最后还有测试代码,和主题没什么关系,但是从以前用python学习数据结构开始我就喜好把测试代码写成假交互式,所以索性贴在这里方便取用。

    In [5]: my_other_list
    Out[5]: [1, 2] # 看到了吧,其实我们本来只想生成[2] 但是却把第一次运行的效果页带了进来

    图片 1图片 2

    In [6]: import time

      1 #include <iostream>  2 #include "linked_list.h"  3 #include <stdlib.h>  4 #include <map>  5   6 using namespace std;  7   8 static map<string, int>stringVal {  9     {"Exit", 0}, 10     {"Printlist", 1}, 11     {"Pushback", 2}, 12     {"Pushfront", 3}, 13     {"Popback", 4}, 14     {"Popfront", 5}, 15     {"Clear", 6}, 16     {"Remove", 7}, 17     {"Removeall", 8}, 18     {"Sort", 9}, 19     {"Getlength", 10}, 20     {"Index", 11}, 21     {"Peekback", 12}, 22     {"Peekfront", 13} 23 }; 24  25 int test_list() { 26     linkList list1; 27     cout << ">> Linked list tesing.n" 28         ">> Enter a direction, namely Printlist, Pushback, Pushfront, Popback, Peekback, " 29         "Popfront, Peekfront, Clear, Remove, Removeall, Sort, Getlength or Index,"  30         "enter Exit to exit." << endl; 31     string direction; 32     DataType parameter; 33     int param; 34     while (1) { 35         cout << ">> "; 36         cout.flush(); 37         cin >> direction; 38         switch(stringVal[direction]) 39         { 40             case 0: 41                 return 0; 42             case 1: 43                 list1.PrintList(); 44                 break; 45             case 2: 46                 cin >> parameter; 47                 list1.PushBack(parameter); 48                 break; 49             case 3: 50                 cin >> parameter; 51                 list1.PushFront(parameter); 52                 break; 53             case 4: 54                 list1.PopBack(); 55                 break; 56             case 5: 57                 list1.PopFront(); 58                 break; 59             case 6: 60                 list1.Clear(); 61                 break; 62             case 7: 63                 cin >> parameter; 64                 list1.Remove(parameter); 65                 break; 66             case 8: 67                 cin >> parameter; 68                 list1.RemoveAll(parameter); 69                 break; 70 /*            case 9: 71                 list1.Sort(); 72                 break;*/ 73             case 10: 74                 param = list1.GetLength(); 75                 cout << ">> " << param << endl; 76                 break; 77             case 11: 78                 cin >> param; 79                 parameter = list1[param]; 80                 cout << ">> " << parameter << endl; 81                 break; 82             case 12: 83                 parameter = list1.PeekBack(); 84                 cout << ">> " << parameter << endl; 85                 break; 86             case 13: 87                 parameter = list1.PeekFront(); 88                 cout << ">> " << parameter << endl; 89         } 90     } 91     return 0; 92 } 93  94 int test_stack() { 95     linkStack stack1; 96     cout << ">> Linked list stack tesing.n" 97         ">> Enter a direction, namely Pushback, Popback or Peekback, " 98         "enter Exit to exit." << endl; 99     string direction;100     DataType parameter;101     int param;102     while (1) {103         cout << ">> ";104         cout.flush();105         cin >> direction;106         switch(stringVal[direction])107         {108             case 0:109                 return 0;110             case 2:111                 cin >> parameter;112                 stack1.PushBack(parameter);113                 break;114             case 4:115                 stack1.PopBack();116                 break;117             case 12:118                 parameter = stack1.PeekBack();119                 cout << ">> " << parameter << endl;120                 break;121         }122     }123     return 0;124 }125 126 int main() {127     test_stack();128     return 0;129 }
    

    In [7]: def report_arg(my_default=time.time()):
       ...:         print(my_default)
       ...:

    假交互式测试代码, test

    In [8]: report_arg() # 第一次执行
    1399562371.32

    In [9]: time.sleep(2) # 隔了2秒

    In [10]: report_arg()
    1399562371.32 # 时间竟然没有变

    这2个例子说明了什么? 字典,集合,列表等等对象是不适合作为函数默认值的. 因为这个默认值实在函数建立的时候就生成了, 每次调用都是用了这个对象的”缓存”. 我在上段时间的分享python高级编程也说到了这个问题,这个是实际开发遇到的问题,好好检查你学过的代码, 也许只是问题没有暴露

    可以这样改:

    复制代码 代码如下:

    def append_to_list(element, to=None):
        if to is None:
            to = []
        to.append(element)
        return to

    二、生成器不保留迭代过后的结果

    复制代码 代码如下:

    In [12]: gen = (i for i in range(5))

    In [13]: 2 in gen
    Out[13]: True

    In [14]: 3 in gen
    Out[14]: True

    In [15]: 1 in gen
    Out[15]: False # 1为什么不在gen里面了? 因为调用1->2,这个时候1已经不在迭代器里面了,被按需生成过了

    In [20]: gen = (i for i in range(5))

    In [21]: a_list = list(gen) # 可以转化成列表,当然a_tuple = tuple(gen) 也可以

    In [22]: 2 in a_list
    Out[22]: True

    In [23]: 3 in a_list
    Out[23]: True

    In [24]: 1 in a_list # 就算循环过,值还在
    Out[24]: True

    三、lambda在闭包中会保存局部变量

    复制代码 代码如下:

    In [29]: my_list = [lambda: i for i in range(5)]

    In [30]: for l in my_list:
       ....:         print(l())
       ....:
    4
    4
    4
    4
    4

    这个问题还是上面说的python高级编程中说过具体原因. 其实就是当我赋值给my_list的时候,lambda表达式就执行了i会循环,直到 i =4,i会保留

    但是可以用生成器

    复制代码 代码如下:

    In [31]: my_gen = (lambda: n for n in range(5))

    In [32]: for l in my_gen:
       ....:         print(l())
       ....:
    0
    1
    2
    3
    4

    也可以坚持用list:

    复制代码 代码如下:

    In [33]: my_list = [lambda x=i: x for i in range(5)] # 看我给每个lambda表达式赋了默认值

    In [34]: for l in my_list:
       ....:         print(l())
       ....:
    0
    1
    2
    3
    4

    有点不好懂是吧,在看看python的另外一个魔法:

    复制代码 代码如下:

    In [35]: def groupby(items, size):
       ....:     return zip(*[iter(items)]*size)
       ....:

    In [36]: groupby(range(9), 3)
    Out[36]: [(0, 1, 2), (3, 4, 5), (6, 7, 8)]

    一个分组的函数,看起来很不好懂,对吧? 我们来解析下这里

    复制代码 代码如下:

    In [39]: [iter(items)]*3
    Out[39]:
    [<listiterator at 0x10e155fd0>,
     <listiterator at 0x10e155fd0>,
     <listiterator at 0x10e155fd0>] # 看到了吧, 其实就是把items变成可迭代的, 重复三回(同一个对象哦), 但是别忘了,每次都.next(), 所以起到了分组的作用
     In [40]: [lambda x=i: x for i in range(5)]
    Out[40]:
    [<function __main__.<lambda>>,
     <function __main__.<lambda>>,
     <function __main__.<lambda>>,
     <function __main__.<lambda>>,
     <function __main__.<lambda>>] # 看懂了吗?

    四、在循环中修改列表项

    复制代码 代码如下:

    In [44]: a = [1, 2, 3, 4, 5]

    In [45]: for i in a:
       ....:     if not i % 2:
       ....:         a.remove(i)
       ....:

    In [46]: a
    Out[46]: [1, 3, 5] # 没有问题

    In [50]: b = [2, 4, 5, 6]

    In [51]: for i in b:
       ....:      if not i % 2:
       ....:          b.remove(i)
       ....:

    In [52]: b
    Out[52]: [4, 5] # 本来我想要的结果应该是去除偶数的列表

    思考一下,为什么 – 是因为你对列表的remove,影响了它的index

    复制代码 代码如下:

    In [53]: b = [2, 4, 5, 6]

    In [54]: for index, item in enumerate(b):
       ....:     print(index, item)
       ....:     if not item % 2:
       ....:         b.remove(item)
       ....:
    (0, 2) # 这里没有问题 2被删除了
    (1, 5) # 因为2被删除目前的列表是[4, 5, 6], 所以索引list[1]直接去找5, 忽略了4
    (2, 6)

    五、IndexError - 列表取值超出了他的索引数

    复制代码 代码如下:

    In [55]: my_list = [1, 2, 3, 4, 5]

    In [56]: my_list[5] # 根本没有这个元素

    IndexError                                Traceback (most recent call last)
    <ipython-input-56-037d00de8360> in <module>()
    ----> 1 my_list[5]

    IndexError: list index out of range # 抛异常了

    In [57]: my_list[5:] # 但是可以这样, 一定要注意, 用好了是trick,用错了就是坑啊
    Out[57]: []

    六、重用全局变量

    复制代码 代码如下:

    In [58]: def my_func():
       ....:         print(var) # 我可以先调用一个未定义的变量
       ....:

    In [59]: var = 'global' # 后赋值

    In [60]: my_func() # 反正只要调用函数时候变量被定义了就可以了
    global

    In [61]: def my_func():
       ....:     var = 'locally changed'
       ....:

    In [62]: var = 'global'

    In [63]: my_func()

    In [64]: print(var)

    global # 局部变量没有影响到全局变量

    In [65]: def my_func():
       ....:         print(var) # 虽然你全局设置这个变量, 但是局部变量有同名的, python以为你忘了定义本地变量了
       ....:         var = 'locally changed'
       ....:

    In [66]: var = 'global'

    In [67]: my_func()

    UnboundLocalError                         Traceback (most recent call last)
    <ipython-input-67-d82eda95de40> in <module>()
    ----> 1 my_func()

    <ipython-input-65-0ad11d690936> in my_func()
          1 def my_func():
    ----> 2         print(var)
          3         var = 'locally changed'
          4

    UnboundLocalError: local variable 'var' referenced before assignment

    In [68]: def my_func():
       ....:         global var # 这个时候得加全局了
       ....:         print(var) # 这样就能正常使用
       ....:         var = 'locally changed'
       ....:

    In [69]: var = 'global'

    In [70]:

    In [70]: my_func()
    global

    In [71]: print(var)
    locally changed # 但是使用了global就改变了全局变量

    七、拷贝可变对象

    复制代码 代码如下:

    In [72]: my_list1 = [[1, 2, 3]] * 2

    In [73]: my_list1
    Out[73]: [[1, 2, 3], [1, 2, 3]]

    In [74]: my_list1[1][0] = 'a' # 我只修改子列表中的一项

    In [75]: my_list1
    Out[75]: [['a', 2, 3], ['a', 2, 3]] # 但是都影响到了

    In [76]: my_list2 = [[1, 2, 3] for i in range(2)] # 用这种循环生成不同对象的方法就不影响了

    In [77]: my_list2[1][0] = 'a'

    In [78]: my_list2
    Out[78]: [[1, 2, 3], ['a', 2, 3]]

    八、python多继承(C3)

    复制代码 代码如下:

    In [1]: class A(object):
       ...:         def foo(self):
       ...:                 print("class A")
       ...:

    In [2]: class B(object):
       ...:         def foo(self):
       ...:                 print("class B")
       ...:

    In [3]: class C(A, B):
       ...:         pass
       ...:

    In [4]: C().foo()
    class A # 例子很好懂, C继承了A和B,从左到右,发现A有foo方法,返回了

    看起来都是很简单, 有次序的从底向上,从前向后找,找到就返回. 再看例子:

    复制代码 代码如下:

    In [5]: class A(object):
       ...:        def foo(self):
       ...:               print("class A")
       ...:

    In [6]: class B(A):
       ...:        pass
       ...:

    In [7]: class C(A):
       ...:        def foo(self):
       ...:               print("class C")
       ...:

    In [8]: class D(B,C):
       ...:        pass
       ...:

    In [9]: D().foo()
    class C # ? 按道理, 顺序是 D->B->A,为什么找到了C哪去了

    这也就涉及了MRO(Method Resolution Order):

    复制代码 代码如下:

    In [10]: D.__mro__
    Out[10]: (__main__.D, __main__.B, __main__.C, __main__.A, object)

    简单的理解其实就是新式类是广度优先了, D->B, 但是发现C也是继承A,就先找C,最后再去找A

    九、列表的+和+=, append和extend

    复制代码 代码如下:

    In [17]: print('ID:', id(a_list))
    ('ID:', 4481323592)

    In [18]: a_list += [1]

    In [19]: print('ID (+=):', id(a_list))
    ('ID (+=):', 4481323592) # 使用+= 还是在原来的列表上操作

    In [20]: a_list = a_list + [2]

    In [21]: print('ID (list = list + ...):', id(a_list))
    ('ID (list = list + ...):', 4481293056) # 简单的+其实已经改变了原有列表
    In [28]: a_list = []

    In [29]: id(a_list)
    Out[29]: 4481326976

    In [30]: a_list.append(1)

    In [31]: id(a_list)
    Out[31]: 4481326976 # append 是在原有列表添加

    In [32]: a_list.extend([2])

    In [33]: id(a_list)
    Out[33]: 4481326976 # extend 也是在原有列表上添加

    十、datetime也有布尔值 这是一个坑

    复制代码 代码如下:

    In [34]: import datetime

    In [35]: print('"datetime.time(0,0,0)" (Midnight) ->', bool(datetime.time(0,0,0)))
    ('"datetime.time(0,0,0)" (Midnight) ->', False)

    In [36]: print('"datetime.time(1,0,0)" (1 am) ->', bool(datetime.time(1,0,0)))
    ('"datetime.time(1,0,0)" (1 am) ->', True)

    十一、'==' 和 is 的区别 我的理解是”is”是判断2个对象的身份, ==是判断2个对象的值

    复制代码 代码如下:

    In [37]: a = 1

    In [38]: b = 1

    In [39]: print('a is b', bool(a is b))
    ('a is b', True)

    In [40]: c = 999

    In [41]: d = 999

    In [42]: print('c is d', bool(c is d))
    ('c is d', False) # 原因是python的内存管理,缓存了-5 - 256的对象

    In [43]: print('256 is 257-1', 256 is 257-1)
    ('256 is 257-1', True)

    In [44]: print('257 is 258-1', 257 is 258 - 1)
    ('257 is 258-1', False)

    In [45]: print('-5 is -6+1', -5 is -6+1)
    ('-5 is -6+1', True)

    In [46]: print('-7 is -6-1', -7 is -6-1)
    ('-7 is -6-1', False)
    In [47]: a = 'hello world!'

    In [48]: b = 'hello world!'

    In [49]: print('a is b,', a is b)
    ('a is b,', False) # 很明显 他们没有被缓存,这是2个字段串的对象

    In [50]: print('a == b,', a == b)
    ('a == b,', True) # 但他们的值相同
    # But, 有个特例
    In [51]: a = float('nan')

    In [52]: print('a is a,', a is a)
    ('a is a,', True)

    In [53]: print('a == a,', a == a)
    ('a == a,', False) # 亮瞎我眼睛了~

    十二、浅拷贝和深拷贝 我们在实际开发中都可以向对某列表的对象做修改,但是可能不希望改动原来的列表. 浅拷贝只拷贝父对象,深拷贝还会拷贝对象的内部的子对象

    复制代码 代码如下:

    In [65]: list1 = [1, 2]

    In [66]: list2 = list1 # 就是个引用, 你操作list2,其实list1的结果也会变

    In [67]: list3 = list1[:]

    In [69]: import copy

    In [70]: list4 = copy.copy(list1) # 他和list3一样 都是浅拷贝

    In [71]: id(list1), id(list2), id(list3), id(list4)
    Out[71]: (4480620232, 4480620232, 4479667880, 4494894720)

    In [72]: list2[0] = 3

    In [73]: print('list1:', list1)
    ('list1:', [3, 2])

    In [74]: list3[0] = 4

    In [75]: list4[1] = 4

    In [76]: print('list1:', list1)
    ('list1:', [3, 2]) # 对list3和list4操作都没有对list1有影响

    # 再看看深拷贝和浅拷贝的区别

    In [88]: from copy import copy, deepcopy

    In [89]: list1 = [[1], [2]]

    In [90]: list2 = copy(list1) # 还是浅拷贝

    In [91]: list3 = deepcopy(list1) # 深拷贝

    In [92]: id(list1), id(list2), id(list3)
    Out[92]: (4494896592, 4495349160, 4494896088)

    In [93]: list2[0][0] = 3

    In [94]: print('list1:', list1)
    ('list1:', [[3], [2]]) # 看到了吧 假如你操作其子对象 还是和引用一样 影响了源

    In [95]: list3[0][0] = 5

    In [96]: print('list1:', list1)
    ('list1:', [[3], [2]]) # 深拷贝就不会影响

    十三、bool其实是int的子类

    复制代码 代码如下:

    In [97]: isinstance(True, int)
    Out[97]: True

    In [98]: True + True
    Out[98]: 2

    In [99]: 3 * True + True
    Out[99]: 4

    In [100]: 3 * True - False
    Out[100]: 3

    In [104]: True << 10
    Out[104]: 1024

    十五、元组是不是真的不可变?

    复制代码 代码如下:

    In [111]: tup = ([],)

    In [112]: tup[0] += [1]

    TypeError                                 Traceback (most recent call last)
    <ipython-input-112-d4f292cf35de> in <module>()
    ----> 1 tup[0] += [1]

    TypeError: 'tuple' object does not support item assignment

    In [113]: tup
    Out[113]: ([1],) # 我靠 又是亮瞎我眼睛,明明抛了异常 还能修改?

    In [114]: tup = ([],)

    In [115]: tup[0].extend([1])

    In [116]: tup[0]
    Out[116]: [1] # 好吧,我有点看明白了, 虽然我不能直接操作元组,但是不能阻止我操作元组中可变的子对象(list)

    这里有个不错的解释Python's += Is Weird, Part II :

    复制代码 代码如下:

    In [117]: my_tup = (1,)

    In [118]: my_tup += (4,)

    In [119]: my_tup = my_tup + (5,)

    In [120]: my_tup
    Out[120]: (1, 4, 5) # ? 嗯 不是不能操作元组嘛?

    In [121]: my_tup = (1,)

    In [122]: print(id(my_tup))
    4481317904

    In [123]: my_tup += (4,)

    In [124]: print(id(my_tup))
    4480606864 # 操作的不是原来的元组 所以可以

    In [125]: my_tup = my_tup + (5,)

    In [126]: print(id(my_tup))
    4474234912

    十六、python没有私有方法/变量? 但是可以有”伪”的

    复制代码 代码如下:

    In [127]: class my_class(object^E):
       .....:     def public_method(self):
       .....:         print('Hello public world!')
       .....:     def __private_method(self): # 私有以双下划线开头
       .....:         print('Hello private world!')
       .....:     def call_private_method_in_class(self):
       .....:         self.__private_method()

    In [132]: my_instance = my_class()

    In [133]: my_instance.public_method()
    Hello public world! # 普通方法

    In [134]: my_instance._my_class__private_method()
    Hello private world! # 私有的可以加"_ + 类名字 + 私有方法名字”

    In [135]: my_instance.call_private_method_in_class()
    Hello private world! # 还可以通过类提供的公有接口内部访问

    In [136]: my_instance._my_class__private_variable
    Out[136]: 1

    十七、异常处理加else

    复制代码 代码如下:

    In [150]: try:
       .....:     print('third element:', a_list[2])
       .....: except IndexError:
       .....:     print('raised IndexError')
       .....: else:
       .....:     print('no error in try-block') # 只有在try里面没有异常的时候才会执行else里面的表达式
       .....:
    raised IndexError # 抛异常了 没完全完成
    In [153]: i = 0

    In [154]: while i < 2:
       .....:     print(i)
       .....:     i += 1
       .....: else:
       .....:     print('in else')
       .....:
    0
    1
    in else # while也支持哦~
    In [155]: i = 0

    In [156]: while i < 2:
       .....:         print(i)
       .....:         i += 1
       .....:         break
       .....: else:
       .....:         print('completed while-loop')
       .....:
    0 # 被break了 没有完全执行完 就不执行else里面的了
    In [158]: for i in range(2):
       .....:         print(i)
       .....: else:
       .....:         print('completed for-loop')
       .....:
    0
    1
    completed for-loop

    In [159]: for i in range(2):
       .....:         print(i)
       .....:         break
       .....: else:
       .....:         print('completed for-loop')
       .....:
    0 # 也是因为break了

    复制代码 代码如下: In [1]: def append_to_list(value, def_list=[]): ...: def_list.append(value) ...: return def_list ...:...

    本文由澳门402永利com发布于编程应用,转载请注明出处:及单向队列,Python技术员无人问津但你应有明白

    关键词: