[python]---牛客(绿盟)

1、[ii for i in range(10)]和(ii for i in range(10))区别
一个是列表生成式,一个式迭代器


# 列表解析生成列表
>>> [i*i for i in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> a = [i*i for i in range(10)]
>>> type(a)
<class 'list'>

# 生成器表达式
>>> b = (i*i for i in range(10))
>>> b
<generator object <genexpr> at 0x102b11620>
>>> type(b)
<class 'generator'>

>>> # 两者之间转换
>>> list(b)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

可参考:https://blog.csdn.net/qq_34358193/article/details/102911407,记录的式生成器和迭代器。

2、new()和__init__()区别,谁先执行

_new_() 是新式类中新出现的类方法,它在构造方法(_init_())之前调用。

__new__()的声明

def __new__(cls, *args, **kwargs):
    pass

_new_()的参数和__init__()一样,但_init_()是在类实例创建之后调用,而_new_()方法正是创建类实例的方法。_init_()有一个参数self,self就是__new__()返回的实例,_init_()在__new__()的基础上完成一些其它初始化的动作,_init_()不需要返回值。

class Foo(object):
    def __init__(self):
        print '__init__'

    def __new__(cls,*args,**kargs):
        print '__new__'
        return super(Foo,cls).__new__(cls,*args,**kargs)
f = Foo()
'''
__new__
__init__
'''

上述代码可证明__new__()方法的调用在__init__()之前。

执行过程如下

f = Foo()
执行Foo的__new__()方法,_new_()方法返回Foo的一个实例
执行__new__()方法返回实例的__init__()方法
由以上可知,_init_()和__new__()的区别主要有以下

_init_() 通常用于初始化一个新实例,控制实例的初始化过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后,它是实例级别的方法

_new_() 通常用于控制生成一个新实例,它是类级别的方法
可利用__new__()实现单例模式

#!/usr/bin/python
# -*- coding: utf-8 -*-
class Singleton(object):
    '''单例模式'''
    def __init__(self):
        print '__init__'

    def __new__(cls,*args,**kargs):
        if not cls.__dict__.get('_Singleton__instance'):
            cls._Singleton__instance = super(Singleton,cls).__new__(cls,*args,**kargs)
        return cls._Singleton__instance

m = Singleton()
n = Singleton()
print m is n
'''
__init__
__init__
True
'''

new() 的特性

new() 方法在类准备将自身实例化时调用;
new() 方法始终都是类的静态方法,即使没有被加上静态方法装饰器;
注意

如果在定义新式类时没有重定义__new__(),Python默认按照MRO顺序调用其父类的__new__()方法来构造该类的实例,因为object是所有新式类的基类,所以一定能找到__new__()方法;

如果新式类重写了__new__()方法,那么可以任意选择一个新式类的__new__()方法来制造实例;

(一定要是新式类,新式类必有__new__(),因为所有新式类都是object的后代,而经典类则没有__new__()方法)

如果__new__()没有返回当前类的实例,那么当前类的__init__()方法是不会被调用的;

如果__new__()返回其他类(新式类或经典类均可)的实例,那么会调用被返回的那个类的构造方法;

也就是说返回谁的实例,就调用谁的__init__()方法,不返回实例,不会调用__init__()方法

class Foo1(object):
   def __init__(self, *args, **kwargs):
       print "Foo1 __init__"

   def __new__(cls, *args, **kwargs):
       return super(Foo1,cls).__new__(cls, *args, **kwargs)  

class Foo2(object):
   def __init__(self):
       print "Foo2 __init__"

   def __new__(cls, *args, **kwargs):
    '''返回Foo1的实例'''
    return Foo1()

class Foo3(object):
   def __init__(self):
       print "Foo3 __init__"

   def __new__(cls, *args, **kwargs):
    pass

foo1 = Foo1()      #Foo1 __init__
print type(foo1)   #<class '__main__.Foo1'>

foo2 = Foo2()      #Foo1 __init__,调用的是Foo1的__init__()方法
print type(foo2)   #<class '__main__.Foo1'>

foo3 = Foo3()
print type(foo3)   #<type 'NoneType'>

————————————————
版权声明:本文为CSDN博主「忧桑的小兔子」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lis_12/article/details/54631089
————————————————
参考链接:https://blog.csdn.net/lis_12/article/details/54631089

3、单例模式

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

1、基于 __new__方法实现(推荐使用,方便)
当我们实现单例时,为了保证线程安全需要在内部加入锁。
我们知道,当我们实例化一个对象时,是先执行了类的__new__方法(我们没写时,默认调用object._new_),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式.

import threading
class Singleton(object):
    _instance_lock = threading.Lock()

    def __init__(self):
        pass


    def __new__(cls, *args, **kwargs):
        if not hasattr(Singleton, "_instance"):
            with Singleton._instance_lock:
                if not hasattr(Singleton, "_instance"):
                    Singleton._instance = object.__new__(cls)  
        return Singleton._instance

obj1 = Singleton()
obj2 = Singleton()
print(obj1,obj2)

def task(arg):
    obj = Singleton()
    print(obj)

for i in range(10):
    t = threading.Thread(target=task,args=[i,])
    t.start()


#打印结果
<__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0>
<__main__.Singleton object at 0x038B33D0>
<__main__.Singleton object at 0x038B33D0>
<__main__.Singleton object at 0x038B33D0>
<__main__.Singleton object at 0x038B33D0>
<__main__.Singleton object at 0x038B33D0>
<__main__.Singleton object at 0x038B33D0>
<__main__.Singleton object at 0x038B33D0>
<__main__.Singleton object at 0x038B33D0>
<__main__.Singleton object at 0x038B33D0>
<__main__.Singleton object at 0x038B33D0>

采用这种方式的单例模式,以后实例化对象时,和平时实例化对象的方法一样 obj = Singleton()
单例模式
实现单例模式的几种方式
1.使用模块
2.使用装饰器
3.使用类
4.基于__new__方法实现(推荐使用,方便)
5.基于metaclass方式实现
相关知识
实现单例模式

转载于:https://www.cnblogs.com/huchong/p/8244279.html

4、装饰器实现单例模式

def Singleton(cls):
    _instance = {}

    def _singleton(*args, **kargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kargs)
        return _instance[cls]

    return _singleton

@Singleton
class A(object):
    a = 1

    def __init__(self, x=0):
        self.x = x
    #定制类
    '''
    __str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串,也就是说,__repr__()是为调试服务的。
    解决办法是再定义一个__repr__()。但是通常__str__()和__repr__()代码都是一样的,所以,有个偷懒的写法
    '''
    def __str__(self):
        return 'A object(x:%s)'%self.x

a1 = A(2)
a2 = A(3)
print(a1)
print(a2)

5、二叉树的序列化和反序列化

【题目】:

二叉树被记录成文件的过程叫作二叉树的序列化,通过文件内容重建原来二叉树的过程叫做二叉树的反序列化。给定一颗二叉树的头节点 head,并已知二叉树节点值的类型为32位整形。请设计一种二叉树序列化和反序列化的方案,并用代码实现。

【思路】:

解法为先序遍历和层遍历两种。

class TreeNode:
  def __init__(self, x):
    self.val = x
    self.left = None
    self.right = None
class Solution:
  def __init__(self):
    self.sIndex = 0

#序列化二叉树
#序遍历二叉树
  def recursionSerialize(self, root):
    series = ''
    if root == None:
      series += ',$'
    else:
      series += (',' + str(root.val))
      series += self.recursionSerialize(root.left)
      series += self.recursionSerialize(root.right)
    return series
  def Serialize(self, root):
    return self.recursionSerialize(root)[1:]
'''
结果
root = TreeNode(11)
root.left = TreeNode(2)
root.right = TreeNode(3)
series = Solution().Serialize(root)
print(series)
>>>11,2,$,$,3,$,$
'''

'''
反序列化
先构建根节点,然后左节点,右节点,同样是递归
注意由于使用的是字符串的表示形式,可以先转化为list,
print(series.split(','))
>>>['11', '2', '$', '$', '3', '$', '$']
'''
  def getValue(self, s, sIndex):  #处理超过10的数字,将数字字符转变为数字
    val = 0
    while ord(s[sIndex]) <= ord('9') and ord(s[sIndex]) >= ord('0'):
      val = val * 10 + int(s[sIndex])
      sIndex += 1
    return val, sIndex - 1

#下面是反序列化的递归函数:
  def Deserialize(self, s):
    if self.sIndex < len(s):
      if s[self.sIndex] == ',':
        self.sIndex += 1
      if s[self.sIndex] == '$':
        return None
      val, self.sIndex = self.getValue(s, self.sIndex)
      treeNode = TreeNode(val)
      self.sIndex += 1
      treeNode.left = self.Deserialize(s)
      self.sIndex += 1
      treeNode.right = self.Deserialize(s)
      return treeNode

转载:https://www.jb51.net/article/157217.htm

发布了35 篇原创文章 · 获赞 10 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_34358193/article/details/103170649
今日推荐