zoukankan      html  css  js  c++  java
  • python面试问题

    python基础

    meta编程(元编程)
    元编程指编写代码的代码
    python中,元编程是指一种构建函数和类的行为,这些函数和类可以通过修改、包装现有代码或生成代码来进行操纵。实现方法是装饰器或者元类(type)

    • 装饰器(不赘述)
    def descr(func):
         @wraps(func)
         def inner(*args, **kwargs):
             print("descr after")
             req = func(*args, **kwargs)
             print("descr before")
             return req
         return inner
    
    • 元编程
      "python中,type生class,class生万物,type则自己生自己"
    >>> class Foo:
    ...  pass
    ...
    >>> type(Foo)
    <class 'type'>
    >>> f = Foo()
    >>> type(f)
    <class '__main__.Foo'>
    >>> type(type)
    <class 'type'>
    

    上面代码显示了类实例,类和type的关系。也可以用.__class__来追溯这一过程。
    下面用type来创造一个类

    >>>class_example = type('class_example', (), {}) # 三个参数分别是类名字,继承的父类和类属性*(方法,属性等)
    >>>print(class_example)
    <class '__main__.class_example'>
    

    同理python使用中经常用到的hasattr和setattr可查询和添加类属性(方法,属性)

    >>> f.attr1
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Foo' object has no attribute 'attr1'
    >>> setattr(Foo,"attr1","reslut attr1")
    >>> f.attr1
    'reslut attr1'
    
    • metaclass
      整个元编程上面都说完了,只是用起来没那么简洁或者没那么oop。metaclass就是生成类的方法(函数)
    def my_meta(classname, father_class, attr):
        return type(classname, father_class, attr)
    
    
    class Foo:
        __metaclass__ = my_meta
    

    上面代码看得出,在创建class的时候python是去找的__metaclass__方法,要是没找到就直接用type,这里我们自定义了一个__metaclass_。(另外子类不继承父类的__metaclass__更深层次的看参考文章1)
    应用实例:
    django的model.Model。在orm(特指django的orm)中所有class都继承了model.Model在Ctrl点击进去看看就明白了

    class Classes(models.Model):
        name = models.CharField(max_length=32)
        institude = models.CharField(max_length=32)
        headteacher = models.ForeignKey("Teacher")
    

    Ctrl点进去models.Model

    class Model(metaclass=ModelBase):  # == __meaclass__ 通过继承的方式显的更oop一些嘛
        ......
    

    Ctrl点进去ModelBase

    class ModelBase(type):  # 这里继承type也证明了一切都是type来的,包括你__metalclass__
        """Metaclass for all models."""
        def __new__(cls, name, bases, attrs, **kwargs):
            super_new = super().__new__
        ......
    

    通过这种继承Model,Model再里面进行操作,最终导致我们在调用orm对象(一个实例)的属性(.age .name)的时候直接返回的是具体的数字或者字符串而不是IntegerField或者CharField的对象。
    忽悠:元编程就是编写代码的代码,python中都知道万物皆对象,对象由类通过new生成,new调用init初始化内存生成实例。那类就是由metaclass调用type生成的。type就是元编程的方式之一。可以通过调用type和三个参数直接生成一个类;也可以在类中添加__metaclass__自定义方法最后return一个type,其实还是type。也可以通过setattr来修改类。广义上讲装饰器也是元编程,它也修改了函数这个对象的代码,所以叫编写代码的代码。比如django的model就是这么实现。装逼的说说......
    参考链接:
    https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python/6581949#6581949
    https://blog.csdn.net/cdlwhm1217096231

    • python2和3的区别
      语法上:print input
      编码上:python3默认使用utf-8
      迭代器:生成列表range
      模块上:注意模块使用的不同
    • 生成器和迭代器
      迭代器是指实现iter和next方法的就是迭代器,生成器是延伸出来的通过yeild实现。
    • 深拷贝
    from copy import deepcopy
    a = [1,2,3,[4,5]]
    b=a
    c = deepcopy(a)   // 深拷贝,copy.copy是浅拷贝。第一层相互不影响,内层影响
    a.append(6)
    b.append(7)
    a[3].append(11)
    print(a)
    print(b)
    print(c)
    
    • map,filter,reduce
      map:将一个列表(可迭代类型)每个元素带入到一个函数中 a = list(map(lambda x:x*x,[1,2,3])) 结果是 [1,4,9]
      filter:同理过滤一个列表 a = list(filter(lambda x:x%2==1, [1,2,3,4,5])) 结果是[1,3,5]
      reduce:将列表前后迭代入函数 a = reduce(lambda x, y: x + y, [1,2,3,4]) 结果是1+2+3+4=10
    • 多肽
      python面向对象的三个特征:封装,继承,多肽
      封装:使用构造方法将内容封装到对象中
      继承:继承父类,python3新式类的c3算法。
    • 字典的排序
      一种方法,多了不记,恶心蛋疼。
      sorted(dict.items(), lambda x:x[0]) # 0表示key排序 1表示值排序 reverse参数
    • 正则匹配中search和match
      match是开头匹配。search是在字符串中,并且match返回<re.Match object; span=(0, 5), match='https'> span表示从哪里匹配到的。search的方法是.group 返回匹配的数据。.groups返回一个列表里面是匹配在括号的内容。

    框架(django主)相关

    • orm查询
      字段设置:
      V=models.CharField(max_length=None<, options>)    #varchar
      V=models.EmailField(<max_length=75, options="">)    #varchar
      V=models.URLField(<verify_exists=true, options="" max_length="200,">)    #varchar
      V=models.FileField(upload_to=None<, max_length=100, options>)    #varchar #upload_to指定保存目录可带格式,
      V=models.ImageField(upload_to=None<, height_field=None, width_field=None, max_length=100, options>)
      V=models.IPAddressField(<
      options>)    #varchar
      V=models.FilePathField(path=None<, match=None, recursive=False, max_length=100, options>) #varchar
      V=models.SlugField(<max_length=50, options="">)    #varchar,标签,内含索引
      V=models.CommaSeparatedIntegerField(max_length=None<, options>)    #varchar
      V=models.IntegerField(<
      options>)    #int
      V=models.PositiveIntegerField(<
      options>)    #int 正整数
      V=models.SmallIntegerField(<
      options>)    #smallint
      V=models.PositiveSmallIntegerField(<
      options>)    #smallint 正整数
      V=models.AutoField(
      options)    #int;在Django代码内是自增
      V=models.DecimalField(max_digits=None, decimal_places=None<, options>)    #decimal
      V=models.FloatField(<
      options>)    #real V=models.BooleanField(
      options)    #boolean或bit
      V=models.NullBooleanField(<
      options>)    #bit字段上可以设置上null值
      V=models.DateField(<auto_now=false, **options="" auto_now_add="False,">)  #date #auto_now最后修改记录的日期;auto_now_add添加记录的日期
      V=models.DateTimeField(<auto_now=false, **options="" auto_now_add="False,">)    #datetime
      V=models.TimeField(<auto_now=false, options="" auto_now_add="False,">)    #time
      V=models.TextField(<
      options>)    #text
      V=models.XMLField(schema_path=None<, **options>)    #text ——————————————————————————–
      V=models.ForeignKey(othermodel<, **options>)    #外键,关联其它模型,创建关联索引
      V=models.ManyToManyField(othermodel<, **options>)    #多对多,关联其它模型,创建关联表
      V=models.OneToOneField(othermodel<, parent_link=False, **options>)    #一对一,字段关联表属性
      字段参数设置:
      null 数据库中字段是否可以为空
      db_column 数据库中字段的列名
      default 数据库中字段的默认值
      primary_key 数据库中字段是否为主键
      db_index 数据库中字段是否可以建立索引
      unique 数据库中字段是否可以建立唯一索引
      unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引
      unique_for_month 数据库中字段【月】部分是否可以建立唯一索引
      unique_for_year 数据库中字段【年】部分是否可以建立唯一索引
      verbose_name Admin中显示的字段名称
      blank Admin中是否允许用户输入为空
      editable Admin中是否可以编辑
      help_text Admin中该字段的提示信息
      choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
      如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)
      error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息;
      字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
      如:{'null': "不能为空.", 'invalid': '格式错误'}
      validators 自定义错误验证(列表类型),从而定制想要的验证规则
      from django.core.validators import RegexValidator
      from django.core.validators import EmailValidator,URLValidator,DecimalValidator,
      MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
      如:
      test = models.CharField(
      max_length=32,
      error_messages={
      'c1': '优先错信息1',
      'c2': '优先错信息2',
      'c3': '优先错信息3',
      },
      validators=[
      RegexValidator(regex='root_d+', message='错误了', code='c1'),
      RegexValidator(regex='root_112233d+', message='又错误了', code='c2'),
      EmailValidator(message='又错误了', code='c3'), ]
      )
      元信息:
      class UserInfo(models.Model):
      nid = models.AutoField(primary_key=True)
      username = models.CharField(max_length=32)
      class Meta:
      # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
      db_table = "table_name"
      # 联合索引
      index_together = [
      ("pub_date", "deadline"),
      ]
      # 联合唯一索引
      unique_together = (("driver", "restaurant"),)
      # admin中显示的表名称
      verbose_name
      # verbose_name加s
      verbose_name_plural
      多对多参数:
      ForeignKey(ForeignObject) # ForeignObject(RelatedField)
      to, # 要进行关联的表名
      to_field=None, # 要关联的表中的字段名称
      on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为
      - models.CASCADE,删除关联数据,与之关联也删除
      - models.DO_NOTHING,删除关联数据,引发错误IntegrityError
      - models.PROTECT,删除关联数据,引发错误ProtectedError
      - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
      - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
      - models.SET,删除关联数据,
      a. 与之关联的值设置为指定值,设置:models.SET(值)
      b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)

                                                        def func():
                                                            return 10
      
                                                        class MyModel(models.Model):
                                                            user = models.ForeignKey(
                                                                to="User",
                                                                to_field="id"
                                                                on_delete=models.SET(func),)
        related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
        related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
        limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
                                    # 如:
                                            - limit_choices_to={'nid__gt': 5}
                                            - limit_choices_to=lambda : {'nid__gt': 5}
      
                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
        db_constraint=True          # 是否在数据库中创建外键约束
        parent_link=False           # 在Admin中是否显示关联数据
      

      OneToOneField(ForeignKey)
      to, # 要进行关联的表名
      to_field=None # 要关联的表中的字段名称
      on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为

                                    ###### 对于一对一 ######
                                    # 1. 一对一其实就是 一对多 + 唯一索引
                                    # 2.当两个类之间有继承关系时,默认会创建一个一对一字段
                                    # 如下会在A表中额外增加一个c_ptr_id列且唯一:
                                            class C(models.Model):
                                                nid = models.AutoField(primary_key=True)
                                                part = models.CharField(max_length=12)
      
                                            class A(C):
                                                id = models.AutoField(primary_key=True)
                                                code = models.CharField(max_length=1)
      

      ManyToManyField(RelatedField)
      to, # 要进行关联的表名
      related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
      related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
      limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:
      # 如:
      - limit_choices_to={'nid__gt': 5}
      - limit_choices_to=lambda : {'nid__gt': 5}

                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
        symmetrical=None,           # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
                                    # 做如下操作时,不同的symmetrical会有不同的可选字段
                                        models.BB.objects.filter(...)
      
                                        # 可选字段有:code, id, m1
                                            class BB(models.Model):
      
                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField('self',symmetrical=True)
      
                                        # 可选字段有: bb, code, id, m1
                                            class BB(models.Model):
      
                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField('self',symmetrical=False)
      
        through=None,               # 自定义第三张表时,使用字段用于指定关系表
        through_fields=None,        # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
                                        from django.db import models
      
                                        class Person(models.Model):
                                            name = models.CharField(max_length=50)
      
                                        class Group(models.Model):
                                            name = models.CharField(max_length=128)
                                            members = models.ManyToManyField(
                                                Person,
                                                through='Membership',
                                                through_fields=('group', 'person'),
                                            )
      
                                        class Membership(models.Model):
                                            group = models.ForeignKey(Group, on_delete=models.CASCADE)
                                            person = models.ForeignKey(Person, on_delete=models.CASCADE)
                                            inviter = models.ForeignKey(
                                                Person,
                                                on_delete=models.CASCADE,
                                                related_name="membership_invites",
                                            )
                                            invite_reason = models.CharField(max_length=64)
        db_constraint=True,         # 是否在数据库中创建外键约束
        db_table=None,              # 默认创建第三张表时,数据库中表的名称
      

    查询参数:
    # 大于,小于
    #
    # models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值
    # models.Tb1.objects.filter(id__gte=1) # 获取id大于等于1的值
    # models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值
    # models.Tb1.objects.filter(id__lte=10) # 获取id小于10的值
    # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值

        # in
        #
        # models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
        # models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
        # order by
        #
        # models.Tb1.objects.filter(name='seven').order_by('id')    # asc
        # models.Tb1.objects.filter(name='seven').order_by('-id')   # desc
        # group by
        #
        # from django.db.models import Count, Min, Max, Sum
        # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
        # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE 
        "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
        # limit 、offset
        #
        # models.Tb1.objects.all()[10:20]
    

    外键查询:
    A表中ForeignKeyB(字段名b),A中有B
    A.b 正常通过点来获取
    A.objects.filter(b__id=0) 链式查询
    B.A_set 反向查

    • 懒加载机制
      queryset默认施行懒加载,在.all()的queryset对象中,_result_cache用来缓存查询结果,只有在print或者list真正使用时候才在_result_cache中有数据。同理这种做法缺点也有容易多次重复查询。解决办法是:select_raleted和prefetch_raleted方法。前者是针对一对一和一对多,后者则是针对多对多或者方向一对多。两者都是一次讲关联数据查询到,防止重复查询。

    • asgi
      同 WSGI 一样,Django 也支持使用 ASGI 来部署,它是为了支持异步网络服务器和应用而新出现的 Python 标准。--来自django文档

    • 接口限流
      django throttle(基于登录未登录次数和频率)

    • 事务装饰器
      @transaction.atomic
      def view(req):
      try:
      ...
      save1 = transaction.savepoint()
      with tansaction.atomic():
      ...
      except:
      transaction.savepoint_rollback(save1) # 回滚到保存点
      transaction.savepoint_commit(save1) # 提交从保存点到当前状态的所有数据库事务操作

    • tornado异步调用同步
      文档推荐@run_on_exector(装饰器)调用同步函数。如若堵死,用concurrent开启多线程。
      数据库相关(mysql主)

    • 聚簇原则
      innodb的b+tree主键和数据行data都在一个子叶上,找到主键就找到了数据行。二级索引保存的是主键值,二级索引至少要两次查询才能找到数据行

    • cache机制(未命中走那两层)
      首先mysql的缓存机制是:
      当命中缓存是,会跳过sql解析,优化,生成计划阶段返回数据。而要命中缓存对sql要求很高,不能包含不确定sql语句(NOW(),CURRENT_DATE(),自定义函数,用户变量,有列权限的表等),且空格,注释的不同也不会命中。一旦涉及到的表或者数据库改变则缓存失效。
      缓存优点和缺点:查询很快,因为缓存存在内存中。缺点是每次的写操作会带来额外的失效缓存的时间;每次生成缓存排它锁一下;一旦某个大表缓存碎片很多,经历过一次修改后,造成雪崩。所以根据优缺点去设置表的缓存。
      mysql就连接层,sql服务层,引擎层和存储层,还搁那里两层。面试的人一般都要显示自己的牛逼。

    • b+tree能存多少数据,计算方式
      假设一个页数据默认16KB,主键一般占用4B,外加其他数据假如是12B。那一个页就有1k(1024)个主键,三阶就能存10**3乘三次就是10亿数据。

    • redis哪些数据结构和语法
      字符串类型:get,set,mset,mget,setbite
      hash类型:hget,hset,hmset,hgetall
      list:lpop,lpush,lindex

    • 关系型和非关系型数据库的区别
      结构上:关系型数据结构固定;非关系型离散,k-v对,文档类型。MongoDB字段和表都是随意添加。
      扩展性:关系型横向拓展不容易
      数据一致性:关系型对ACID要求严格

    • 为什么使用monggodb,为什么使用mysql
      MongoDB新增数据或者增加字段非常容易,mysql则是我们结构性字段,一般不修改。修改就是大修改。

    算法
    匹配一个IP地址

    import re
    #简单的匹配给定的字符串是否是ip地址,下面的例子它不是IPv4的地址,但是它满足正则表达式
    if re.match(r"^(?:[0-9]{1,3}.){3}[0-9]{1,3}$", "272.168,1,1"):
        print "IP vaild"
    else:
        print "IP invaild"
    #精确的匹配给定的字符串是否是IP地址
    if re.match(r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", "223.168.1.1"):
        print "IP vaild"
    else:
        print "IP invaild"
    #简单的从长文本中提取中提取ip地址
    string_ip = "is this 289.22.22.22 ip ?
    result = re.findall(r"(?:[0-9]{1,3}.){3}[0-9]{1,3}", string_ip)
    if result:
        print result
    else:
        print "re cannot find ip"
    #精确提取IP
    result = re.findall(r"(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)", string_ip):
    if result:
        print result
    else:
        print "re cannot find ip
    
    • 冒泡,归并和快速
    # 冒泡 先排最大的 所以第二循环去除最后len(arr) - 1
    # def bubbleSort(arr):
    #     g = 0
    #     for i in range(1, len(arr)):
    #         for j in range(0, len(arr)-i):
    #             g += 1
    #             if arr[j] > arr[j+1]:
    #                 arr[j], arr[j + 1] = arr[j + 1], arr[j]
    #             print(arr)
    #     print(g)
    #     return arr
    # bubbleSort(a)
    
    # 归并 无限分成两段 默认每段都是有序的 俩俩比对
    # def merge(l, r):
    #     req = []
    #
    #     while l and r:
    #         if l[0] < r[0]:
    #             req.append(l.pop(0))
    #         else:
    #             req.append(r.pop(0))
    #
    #     if l:
    #         for i in l:
    #             req.append(i)
    #     if r:
    #         for i in r:
    #             req.append(i)
    #     return req
    #
    # def merge_s(a):
    #     if len(a) < 2:
    #         return a
    #     mid = round(len(a)/2)
    #     l = a[0:mid]
    #     r = a[mid:]
    #     return merge(merge_s(l), merge_s(r))
    #
    # print(merge_s(a))
    # 
    # 快速排序
    # def quicksort(arr):
    #     if len(arr) <= 1:
    #         return arr
    #     pivot = arr[round(len(arr) / 2)]
    #     left = [x for x in arr if x < pivot]
    #     middle = [x for x in arr if x == pivot]
    #     right = [x for x in arr if x > pivot]
    #     return quicksort(left) + middle + quicksort(right)
    
    

    网络和web

    • tcp/ip五层结构
      应用层:应用程序和他们的协议存放的地方。HTTP,SMTP,FTP
      运输层:运送应用程序端点之间传送应用层报文。TCP,UDP
      网络层:负责主机间的数据交互 IP
      链路层:负责路由数据报文
      物理层:负责更进一步
    • 上下文管理器如何切换
      1挂起被中断的进程或者线程(系统中断,用户yeild)2 讲挂起的进程信息(堆栈,指令行)保存到cpu的一个内存中(PCB) 3cpu寄存器加载下个进程在PCB的信息 4在被中断的位置找到指令行执行
    • 内核态和用户态
      系统执行进程的两种状态。区别在于权力的大小:内核态是cpu ring0级用户态是ring4级别,内核态可以调配系统资源(cpu,内存,文件和网络等)而限制用户态的权力。用户态用过系统调用转为内核态
  • 相关阅读:
    tomcat虚拟目录配置
    关于JS闭包
    数据列表里结合负边距做间隔线的技巧需注意的小细节
    前端优化技巧笔记
    浏览器工作原理相关笔记
    工作小心得(关于绝对定位元素)
    关于定位和溢出处理的一些小经历
    关于定位和z-index的一些小经历
    fullpage实现(-)
    移动端布局-实例
  • 原文地址:https://www.cnblogs.com/khal-Cgg/p/14533636.html
Copyright © 2011-2022 走看看