python 面向对象练习

请用类代码简答实现stack 栈

  • Stack() 创建一个新的空栈
  • push(item) 添加一个新的元素item到栈顶
  • pop() 弹出栈顶元素
  • peek() 返回栈顶元素
  • is_empty() 判断栈是否为空
  • size() 返回栈的元素个数
# 实现一个栈stack,后进先出

'''
class Stack:
    def __init__(self):
        self.items = []

    def is_empty(self):
        # 判断是否为空
        return self.items == []

    def push(self,item):
        # 加入元素
        self.items.append(item)

    def pop(self):
        # 弹出元素
        return self.items.pop()

    def peek(self):
        # 返回栈顶元素
        return self.items[len(self.items)-1]

    def size(self):
        # 返回栈的大小
        return len(self.items)

if __name__ == "__main__":
    stack = Stack()
    stack.push("H")
    stack.push("E")
    stack.push("L")
    print(stack.size())  # 3
    print(stack.peek())  # L 
    print(stack.pop())   # L
    print(stack.pop())   # E
    print(stack.pop())   # H
'''

谈谈你对面向对象的理解

三大特性以及解释?

面对对象是一种编程思想,以类的眼光来来看待事物的一种方式。将有共同的属性和方法的事物封装到同一个类下面。

继承:将多个类的共同属性和方法封装到一个父类下面,然后在用这些类来继承这个类的属性和方法

封装:将有共同的属性和方法封装到同一个类下面

  • 第一层面:创建类和对象会分别创建二者的名称空间,我们只能用类名.或者obj.的方式去访问里面的名字,这本身就是一种封装
  • 第二层面:类中把某些属性和方法隐藏起来(或者说定义成私有的),只在类的内部使用、外部无法访问,或者留下少量接口(函数)供外部访问。

多态:Python天生是支持多态的。指的是基类的同一个方法在不同的派生类中有着不同的功能

Python面向对象中的继承有什么特点

python 两种类:经典类 新式类
python3 新式类 —— 都默认继承object class Animal(object): == class Animal:
python2 经典类和新式类 并存
        class Animal:  经典类 —— 继承顺序 个别使用方法
        class Animal(object):  新式类

继承分为单继承和多继承
Python是支持多继承的
如果没有指定基类,python的类会默认继承object类,object是所有python类的基类,它提供了一些常见方法(如__str__)的实现。

1、对象可以调用自己本类和父类的所有方法和属性, 先调用自己的 自己没有才调父类的。谁(对象)调用方法,方法中的self就指向谁



class Foo:
    def __init__(self):
        self.func()

    def func(self):
        print('Foo.func')

class Son(Foo):
    def func(self):
        print('Son.func')

面向对象深度优先和广度优先是什么?

Python的类可以继承多个类,Python的类如果继承了多个类,那么其寻找方法的方式有两种
当类是经典类时,多继承情况下,会按照深度优先方式查找  py3
当类是新式类时,多继承情况下,会按照广度优先方式查找  py2
简单点说就是:经典类是纵向查找,新式类是横向查找
经典类和新式类的区别就是,在声明类的时候,新式类需要加上object关键字。在python3中默认全是新式类

面向对象中super的作用?

用于子类继承基类的方法

class FooParent(object):
    def __init__(self):
        self.parent = 'I\'m the parent.'
        print('Parent')
        print('1111')

    def bar(self, message):
        print("%s from Parent" % message)


class FooChild(FooParent):
    def __init__(self):
        # super(FooChild,self) 首先找到 FooChild 的父类(就是类 FooParent),然后把类B的对象 FooChild 转换为类 FooParent 的对象
        super(FooChild, self).__init__()
        print('Child')

    # def bar(self, message):
    #     # super(FooChild, self).bar(message)
    #     print('Child bar fuction')
    #     print(self.parent)


if __name__ == '__main__':
    fooChild = FooChild()
    fooChild.bar('HelloWorld')

列举面向对象中带双下划线的特殊方法,如:newinit

__new__:生成实例
__init__:生成实例的属性
__call__:实例对象加( )会执行def __call__:... 方法里边的内容。

__del__:析构方法,当对象在内存中被释放时,自动触发执行。如当 del obj 或者应用程序运行完毕时,执行该方法里边的内容。

__enter__和__exit__:出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量;with中代码块执行完毕时执行__exit__里边的内容。

__module__:表示当前操作的对象在那个模块   obj.__module__
__class__ :表示当前操作的对象的类是什么     obj.__class__

__doc__:类的描述信息,该描述信息无法被继承

__str__:改变对象的字符串显示 print函数 --->obj.__str__()
__repr__:改变对象的字符串显示 交互式解释器 --->obj.__repr__()
__format__:自定制格式化字符串

__slots__:一个类变量 用来限制实例可以添加的属性的数量和类型  

__setitem__,__getitem,__delitem__:

如何判断是函数还是方法?

看他的调用者是谁,如果是类,就需要传入一个参数self的值,这时他就是一个函数,

如果调用者是对象,就不需要给self传入参数值,这时他就是一个方法

print(isinstance(obj.func, FunctionType))   # False

print(isinstance(obj.func, MethodType))    # True

函数:

  函数是封装了一些独立的功能,可以直接调用,python内置了许多函数,同时可以自建函数来使用。

方法:

  方法和函数类似,同样封装了独立的功能,但是方法是需要通过对象来调用的,表示针对这个对象要做的操作,使用时采用点方法。

静态方法和类方法区别?

尽管 classmethod 和 staticmethod 非常相似,但在用法上依然有一些明显的区别。classmethod 必须有一个指向类对象的引用作为第一个参数,而 staticmethod 可以没有任何参数。

class Num:
    # 普通方法:能用Num调用而不能用实例化对象调用   
    def one():  
        print ('1')
 
    # 实例方法:能用实例化对象调用而不能用Num调用
    def two(self):
        print ('2')
 
    # 静态方法:能用Num和实例化对象调用
    @staticmethod 
    def three():  
        print ('3')
 
    # 类方法:第一个参数cls长什么样不重要,都是指Num类本身,调用时将Num类作为对象隐式地传入方法   
    @classmethod 
    def go(cls): 
        cls.three() 
 
Num.one()          #1
#Num.two()         #TypeError: two() missing 1 required positional argument: 'self'
Num.three()        #3
Num.go()           #3
 
i=Num()                
#i.one()           #TypeError: one() takes 0 positional arguments but 1 was given         
i.two()            #2      
i.three()          #3
i.go()             #3 

列举面向对象中的特殊成员以及应用场景

__call__

__new__

__init__

__doc__

__class__

__del__

__dict__

__str__

在falsk源码用到......

什么是反射?以及应用场景?

反射的核心本质就是以字符串的形式去导入个模块,利用字符串的形式去执行函数。

Django中的 CBV就是基于反射实现的。

4个方法
getattr、hasattr、delattr和setattr较为全面的实现了基于字符串的反射机制

metaclass作用?以及应用场景?

不知道
class MyType(type):
    def __call__(self, *args, **kwargs):
        return 'MyType'
  
  
class Foo(object, metaclass=MyType):
    def __init__(self):
        return 'init'
  
    def __new__(cls, *args, **kwargs):
        return cls.__init__(cls)
  
    def __call__(self, *args, **kwargs):
        return 'call'
  
  
obj = Foo()
print(obj)  # MyType

用尽量多的方法实现单例模式。

1:使用模块
Python的模块就是天然的单例模式。
因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。
因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。
例如:
class V1(object):
    def foo(self)
        pass
V1 = V1()
将上面代码保存在文件test.py,要使用时,直接在其他文件中导入此文件中的对象,这个对象既是单例模式的对象

如:from a import V1

2:使用装饰器
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)


3:使用类

4:基于__new__方法实现
当我们实例化一个对象时,是先执行了类的__new__方法
当:(我们没写时,默认调用object.__new__),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式

什么是面向对象的mro

mro就是方法解析顺序
super 继承都用到

isinstance作用以及应用场景?

isinstance(对象,类)  判断这个对象是不是这个类或者这个类的子类的实例化

# # 判断a 属不属于A这个类(可以判断到祖宗类)
class A:
    pass

class B(A):
    pass
a = A()
b = B()
print(isinstance(b,A)) # ===> True  判断到祖宗类

# 任何与object都是True,内部都继承object
class A:pass
a = A()  # 实例化
print(isinstance(a,object))  #  True

什么是断言?应用场景?

ssert 是的作用?断言
条件成立(布尔值为True)则继续往下,否则跑出异常,一般用于:满足某个条件之后,才能执行,否则应该跑出异常。

写API的时候,继承GenericAPIView

class GenericAPIView(views.APIView):
                    """
                    Base class for all other generic views.
                    """
                    # You'll need to either set these attributes,
                    # or override `get_queryset()`/`get_serializer_class()`.
                    # If you are overriding a view method, it is important that you call
                    # `get_queryset()` instead of accessing the `queryset` property directly,
                    # as `queryset` will get evaluated only once, and those results are cached
                    # for all subsequent requests.
                    queryset = None
                    serializer_class = None

                    # If you want to use object lookups other than pk, set 'lookup_field'.
                    # For more complex lookup requirements override `get_object()`.
                    lookup_field = 'pk'
                    lookup_url_kwarg = None

                    # The filter backend classes to use for queryset filtering
                    filter_backends = api_settings.DEFAULT_FILTER_BACKENDS

                    # The style to use for queryset pagination.
                    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

                    def get_queryset(self):

                        assert self.queryset is not None, (
                            "'%s' should either include a `queryset` attribute, "
                            "or override the `get_queryset()` method."
                            % self.__class__.__name__
                        )

                        queryset = self.queryset
                        if isinstance(queryset, QuerySet):
                            # Ensure queryset is re-evaluated on each request.
                            queryset = queryset.all()
                        return queryset

猜你喜欢

转载自www.cnblogs.com/saoqiang/p/12453738.html