• 第四章 面向对象


    1、简述面向对象的三大特性。

      继承:如果多个类中有共同的方法,就可以把共同的方法写在基类也就是父类中,可以供其所有的子类也就是派生类使用,这样的话就不用将这个方法写很多遍了,使得代码更加简洁,提高了代码的编写效率,子类可以继承父类的非私有属性和方法。

      在视图、版本、认证、分页中使用过。

      封装:把多个相关的方法、属性封装在一个类中。

      多态:有多种表现形式。

    2、什么是鸭子模型?

      鸭子模型:如果一个东西的叫声像鸭子,走路姿势像鸭子,游泳姿势像鸭子,那么就可以看作这个东西是鸭子。

      在面向对象中,一个类的有效定义不是由它继承的类或者特定的借口决定的,而是由当前方法和属性决定的。

    3、super的作用?

      super()函数是用来调用父类的一个方法。在多继承中,为了避免在两个父类由同样的方法时调用出错的问题,就需要super方法了,单继承中,如果子类的方法和父类重名了,也需要super()方法用super也是一个良好的习惯,

      会在以后避免很多出错。

    4、mro是什么?

      当两个父类中出现重名方法的时候,如何处理他们的继承关系,即MRO(method resolution order)方法解析顺序问题。

    5、什么是c3算法。

      c3算法最早是用于lisp,后来用到python中解决深度优先搜索中不满足本地优先级和单调性的问题。(用来计算类的MRO)

      实例:

    class A:
        pass
    class B(A):
        pass
    class C(A):
        pass
    class D(B, C):
        pass
    class E(C, A):
        pass
    class F(D, E):
        pass
    class M:
        pass
    class N(M):
        pass
    class P(E, A):
        pass
    class X:
        pass
    class Q(P,N,X):
        pass
    class G(Q, F):
        pass
    class H(G, F):
        pass

      计算H的mro:

    L(A) = A
    L(B) = B + L(A) + BA                 BA
    L(C) = C + L(A) + A                  CA
    L(D) = D + L(B) +L(C) + BC           DBCA
    L(E) = E + L(C) +L(A) + CA           ECA
    L(F) = F +L(D) + L(E) + DE           F + DBCA + ECA = FDBECA
    L(M) = M
    L(N) = N + L(M) + M                  NM
    L(P) = P + L(E) +L(A) + EA           PECA
    L(X) = X
    L(Q) = Q + L(P) + L(N) + L(X) + PNX   QPECANMX
    L(G) = G + L(Q) + L(F) + QF           G + QPECANMX + FDBECA = GQPFDBECANMX
    L(H) = H + L(G) + L(F) + GF           H + GQPFDBECANMX + FDBECA = HGQPFDBECANMX

    6、列举面向对象中带双下划线的特殊方法。

      __init__: 构造函数,在生成对象时调用。

      __del__: 析构函数,释放对象时使用。

      __repr__: 打印,转换。

      __new__: 构造类的实例化。

      __setitem: 按照索引赋值。

      __getitem__: 按照索引获取值。

      __len__:获取长度。

      __call__:调用。

    7、双下划线和单下划线的区别。

      单下划线:方法或者属性前面,认为它时该方法或者属性为该类的私有属性或者方法。

      双下划线:python设计此的真正目的是为了避免字类覆盖父类的方法。

      开头结尾双下划线:一般来说__this__这种开头结尾都加双下划线的方法表示这是python自己调用的,你不要调用。

    8、实例变量和类变量的区别。

      类变量:定义在类里面,通过类名或对象名引用,如果是通过对象名引用,会先找有没有这个同名的实例变量,如果没有,引用到的才是类变量,类变量的更新,只能通过类名,形如 类名.a = 55 ,不要指望通过实例引用类变量来更

      新类变量。

      实例变量: 定义在方法里面的变量,一般在__init__里面,只能通过对象名引用,实例变量的增加、更新形式,形如self.a = 55 。

      区别在于,类变量属于类,一个方法将其改变,其他方法调用的就是改变之后的了,实例变量是属于方法私有的,方法将其改变之后,对其他方法没有影响。

    9、静态方法和类方法的区别。

      类方法:定义:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法);

      静态方法:定义:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法;调用:实例对象和类对象都可以调用。

    10、isinstance 和 type 的作用。

      isinstance: 判断一个对象是某个类或子类的实例。(isinstance(object,type-or-tuple-or-class) -> bool)

      type: 得到传入的object的类型。(type(object)--类型)

    11、有用过with statement吗?它的好处是什么。

      用过,打来文件的时候,with的作用是在代码执行结束后,自动关闭文件,不论程序是以何种方式结束的,如果执行代码过程中发生异常,with会在外部异常前关闭文件。

    12、下列数据哪些是不可迭代的?

      object不可迭代

    13、实现一个singleton单例类,要求遵循基本语言编程规范。

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

    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
    
    
    a1 = A(2)
    a2 = A(3)

    14、请描述with的用法,如果自己的类需要支持with 语句,需要怎么书写?

      with 后面的语句被求值后返回对象的'__enter__()'方法被调用,这个方法的返回值将会返回给as后面的变量。

      当with后面的代码全部执行完后将调用前面返回对象的'__exit__()'方法。

      只需要在类里写入__enter__()方法和__exit__()方法即可使用with.

    15、如何判断一个对象是可调用对象?

      1、使用内置函数callable函数:可以检测对象是否可以调用,返回True,不一定可以调用,但是返回False,一定不可以调用。

      2、判断对象是否有__call__方法。

      3、判断类型是否是FunctionTypetype(func) is FunctionType 或者 isinstance(func, FunctionType)

      能实现类中__call__()方法的就是可调用类。

    16、请实现一个栈

    class zhan(object):
    
        def __init__(self):
            self.items = []
    
        def panduan(self):
            return self.items == []
    
        def size(self):
            return len(self.items)
    
        def peek(self):
            return self.items[len(self.items) - 1]
    
        def push(self, item):
            self.items.append(item)
    
        def pop(self):
            return self.items.pop()
    
    
    obj = zhan()
    obj.push('h')
    obj.push('a')
    obj.push('s')
    print(obj.size())
    print(obj.peek())
    print(obj.pop())
    print(obj.peek())
    print(obj.size())
    print(obj.pop())
    print(obj.size())
    print(obj.panduan())

    17、关于python 类的继承不正确的说法是?

      python的类无法继承,只能有一个父类,可以继承,但是不能继承父类的构造函数。(以上说法是不正确的)

    18、------

    19、请用两个队列实现一个栈(给出为代码即可)

    class zhan1(object):
    
        def __init__(self):
            self.l1 = []
            self.l2 = []
    
        def add(self, a):
            if len(self.l1) == 0:
                self.l2.append(a)
            if len(self.l2) == 0:
                self.l1.append(a)
    
        def pop(self, ):
            if len(self.l1) == 0:
                for i in self.l2[:-1]:
                    self.l1.append(i)
                self.l2.clear()
            elif len(self.l2) == 0:
                for i in self.l1[:-1]:
                    self.l2.append(i)
                self.l1.clear()
            else:
                print('栈已经为空')
    
        def check(self):
            if len(self.l1) == 0:
                print(self.l2)
            elif len(self.l2) == 0:
                print(self.l1)
    
    
    obj = zhan1()
    obj.add('a')
    obj.add('b')
    obj.add('c')
    obj.check()
    obj.pop()
    obj.check()
    obj.pop()
    obj.check()
    obj.add('d')
    obj.check()
    obj.pop()
    obj.check()

      结果:

    ['a', 'b', 'c']
    ['a', 'b']
    ['a']
    ['a', 'd']
    ['a']

    20、已知如下链表类,请实现单链表逆置。

    class Node:
        def __init__(self, value=None, next=None):
            self.value = value
            self.next = next
    
    def nizhuan(link):
        pre = link
        cur = link.next
        pre.next = None
        while cur:
            tem = cur.next
            cur.next = pre
            pre = cur
            cur = tem
        return pre
    
    
    if __name__ == '__main__':
        link = Node(1, Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8, Node(9)))))))))
        root = nizhuan(link)
        while root:
            print(root.value)
            root = root.next

    21、类的加载顺序

      构造>静态>父类

    22、参考下面代码片段

    class Context:
        pass
    
    
    with Context() as ctx:
        ctx.do_something

      结果:

    class Context(object):

    def __enter__(self):
    print('enter')
    return self

    def __exit__(self, exc_type, exc_val, exc_tb):
    print()

    def do_something(self):
    print('a')


    with Context() as ctx:
    ctx.do_something()

    23、下面代码输出时什么?请给出答案并解释。

    class Parent(object):
        x = 1
    
    class Child1(Parent):
        pass
    
    class Child2(Parent):
        pass
    
    print(Parent.x)
    print(Child1.x)
    print(Child2.x)
    
    Child1.x = 2
    print(Parent.x)
    print(Child1.x)
    print(Child2.x)
    
    Parent.x = 2
    print(Parent.x)
    print(Child1.x)
    print(Child2.x)

      结果:

    1
    1
    1
    1
    2
    1
    2
    2
    2

      解释:父类中的变量类似于全局变量,只能在全局作用域里修改,子类中的属于局部变量,局部变量中对全局变量进行修改只能作用于自己类中,无法改变去他作用域的该变量。

    24、

    25、请给出下面代码片段的输出,请简述上面代码需要改进的地方。

    class singlenton:
        _instance = None
        def __new__(cls, *args, **kwargs):
            print('new')
            if cls._instance is None:
                print('Create')
                cls._instance = super().__new__(cls, *args, **kwargs)
            return  cls._instance
    
        def __init__(self):
            print('initalize')
            self.prop = None
    
    s1 = singlenton()
    s2 = singlenton()

      结果:

    new
    Create
    initalize
    new
    initalize

      改进:应该把__init__函数放在最上面,

    26、请简单解释python中的静态方法和类方法,并将以下代码填写完整。

      类方法:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法)

      静态方法:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法;调用:实例对象和类对象都可以调用。

     class A(object):
        def foo(self,x)
             print ‘executing foo(%s, %s)‘%(self,x)
    
        @classmethod
        def class_foo(cls,x):
            print ‘executing class_foo(%s, %s)‘%(cls,x)
    
        @staticmethod
         def static_foo(x):
             print ‘executing static_foo(%s)‘%(x)
     
    a= A()
    # 调用 foo函数,参数传入 1
    a.foo(1)
    # 调用 class_foo函数,参数传入 1
    A.class_foo(1)
    # 调用 static_foo函数,参数传入 1
    A.static_foo(1) /  a.ststic_foo(1)

    27、

    28、编程实现一个先进先出的队列类,能追定初识化时的队列大小。

    class Queue(object):
        def __init__(self, size):
            self.__size = size
            self.__queue = []
    
        def enqueue(self, x):
            if len(self.__queue) < self.__size:
                self.__queue.insert(0, x)
            else:
                return 'The queue is full!!!'
    
        def dequeue(self):
            return None if not len(self.__queue) else self.__queue.pop()
    
        def is_empty(self):
            return not len(self.__queue)
    
        def isfull(self):
            return len(self.__queue) == self.__size
    
    s = Queue(2)
    print(s.is_empty())
    s.enqueue(1)
    s.enqueue(2)
    print(s.isfull())
    print(s.dequeue())
    print(s.dequeue())
    print(s.is_empty())

       

      

      

      

      

      

  • 相关阅读:
    Apache httpd和JBoss构建高可用集群环境
    Ubuntu 14.04下NFS安装配置
    Ubuntu 14.04 安装 JDK 7.0
    Docker第三方项目小结
    Shipyard远程API
    Linux软件管理——yum命令详解
    Quartz集群原理及配置应用
    Rsync原理介绍及配置应用
    python构造wireshark可以解析的LTE空口数据
    A Simple Web Server
  • 原文地址:https://www.cnblogs.com/490144243msq/p/11508155.html
Copyright © 2020-2023  润新知