• 今天面试了一家公司,感觉表现的不是很好,记录一下面试的试题。
  • python基础部分
  1. python 是一门什么样的语言面向对象的语言有那些,python的面向对象和Java面向对象的区别
  1. Python是一门动态解释型的强类型定义语言。
  2. 我们需要了解编译型和解释型、静态语言和动态语言、强类型定义语言和弱类型定义语言这6个概念就可知晓。
  3. 编译型和解释型各有利弊。前者由于程序执行速度快,同等条件下对系统要求较低,因此像开发操作系统、大型应用程序、数据库系统时都采用它,像C/C++、Pascal/Object Pascal(Delphi)、VB等基本都可视编译语言,而一些网页脚本、服务器脚本及辅助开发接口这样的对速度要求不高、对不同系统平台间的兼容性有一定要求的程序则通常使用解释型语言,如Java、JavaScript、VBScript、Perl、Python等等。(我个人认为Java属于混合语言,介于编译和解释之间,更偏向于编译语言)
  4. 动态类型语言是指在运行期间才去做数据类型检查的语言,也就是说,在用动态类型 语言编译的时,永远也不用给任何变量指定数据类型,该语言会在你第一次赋值给变量时,在内部将数据类型记录下来。
  5. 强制数据类型定义的语言。也就是说,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。举个例子,如果您定义了一个整型变量a,那么程序根本不能将a当做字符串类型处理。强类型定义语言是类型安全的语言。
  1. 面向对象的语言有那些,python的面向对象和Java面向对象的区别
  1. 面向对象的语言:C++、Java、C#、PHP等
  2. python可面向对象编程,可以不按照面向对象编程。
    java就必须面向对象编程了,必须建个类。
  3. python可以动态的绑定属性和方法。
  4. 初始化self|初始化this|
  5. 访问权限控制使用‘__’|访问修饰符:private,default,protected,public|
  6. 方法参数的类型不能在函数定义中限制|参数类型需在函数中声明|
  1.  python 包和模块的概念,init.py文件什么时候执行
  1. 在Python中,一个.py文件就称之为一个模块(Module)
  2. 为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。
  3. 请注意,每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。
  4. __init__.py 定义__all__用来模糊导入 
  5. __init__.py 控制着包的导入行为。 
  6. 当用import导入该目录时,会执行__init.py__里面的代码。程序加载到包的时候就已经分配了内存。
  1. “”“作用,用法;”“”和“”的区别
  1. 单引号和双引号都可以用来表示一个字符串
  2. Python三引号允许一个字符串跨多行,字符串中可以包含换行符、制表符以及其他特殊字符。
  3. 在表达式中没有变量时,我们可以使用三引号来让sql语句更清晰
  1. python 自省机制
  1. 在计算机编程中,自省是指这种能力:检查某些事物以确定它是什么、它知道什么以及它能做什么。自省向程序员提供了极大的灵活性和控制力。
  2. Python中比较常见的自省机制(函数用法)有:dir(),type(),hasattr(),isinstance()等,通过这些函数,我们能够在运行时得知对象的类型,判断对象是否存在某个属性,访问对象属性。
  1. 判断一个对象是否有某个方法,属性,获取属性
  1. dir([obj]):
    调用这个方法将返回包含obj大多数属性名的列表(会有一些特殊的属性不包含在内)。obj的默认值是当前的模块对象。
  2. hasattr(obj, attr): 
    这个方法用于检查obj是否有一个名为attr的值的属性,返回一个布尔值。
  3. getattr(obj, attr): 
    调用这个方法将返回obj中名为attr值的属性的值,例如如果attr为’bar’,则返回obj.bar。
  4. setattr(obj, attr, val):
    调用这个方法将给obj的名为attr的值的属性赋值为val。例如如果attr为’bar’,则相当于obj.bar = val。
  1. 类方法和静态方法的区别
  1. 实例方法只能被实例对象调用,静态方法(@staticmethod装饰的方法)、类方法(@classmethod装饰的方法),可以被类或者类的实例对象调用。
  2. 实例方法第一个参数必须要默认传实例对象,一般习惯使用self,它表示具体的实例本身。静态方法参数没有要求,这个方法可当成一个普通的函数使用。类方法第一个参数必须要默认传类,一般习惯使用cls,它表示这个类本身。 
  3. 静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,逻辑上属于类,但是和类本身没有关系,也就是说在静态方法中,不会涉及到类中的属性和方法的操作。可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护。
  4. 静态方法与类方法一旦被调用,内存地址即确定。通过类调用和通过实例化对象调用的结果完全一样。
  1. 装饰器相关
  1. 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象。
  2. 它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。
  3. 装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。
  4. 修改是封闭的,对拓展是开放的。
  1. python设计模式
  1. **七大设计原则:**
    1. 单一职责原则:一个类负责一项职责。
    2. 里氏替换职责:继承与派生的规则。(子类可替换父类)
    3. 依赖倒转原则:高层模块不应该依赖底层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。即针对接口编程,不要针对实现编程。
    4. 接口隔离原则:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。
    5. 迪米特法则:高内聚,低耦合。
    6. 开闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
    7. 组合/聚合复用原则:尽量使用组合和聚合,少使用继承的关系来达到复用的原则。
    **24种设计模式:**
    **一、创建型模式**
    1. 抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。
    2. 生成器模式:使用生成器模式封装一个产品的构造过程,并允许按步骤构造。将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
    3. 工厂模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
    4. 原型模式:当创建给定类的实例过程很昂贵或很复杂时,就使用原形模式。
    5. 单例了模式:确保一个类只有一个实例,并提供全局访问点。
    6. 多例模式:在一个解决方案中结合两个或多个模式,以解决一般或重复发生的问题。
    **二、结构型模式**
    1. 适配器模式:将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。对象适配器使用组合,类适配器使用多重继承。
    2. 桥接模式:使用桥接模式通过将实现和抽象放在两个不同的类层次中而使它们可以独立改变。
    3. 组合模式:允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
    4. 装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
    5. 外观模式:提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
    6. 亨元模式:如想让某个类的一个实例能用来提供许多”虚拟实例”,就使用蝇量模式。
    7. 代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问。
    **三、行为型模式**
    1. 责任链模式:通过责任链模式,你可以为某个请求创建一个对象链。每个对象依序检查此请求并对其进行处理或者将它传给链中的下一个对象。
    2. 命令模式:将”请求”封闭成对象,以便使用不同的请求,队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
    3. 解释器模式:使用解释器模式为语言创建解释器。
    4. 迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
    5. 中介者模式:使用中介者模式来集中相关对象之间复杂的沟通和控制方式。
    6. 备忘录模式:当你需要让对象返回之前的状态时(例如, 你的用户请求”撤销”),你使用备忘录模式.
    7. 观察者模式:在对象之间定义一对多的依赖, 这样一来, 当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。
    8. 状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好象改了它的类。
    9. 策略模式:定义了算法族,分别封闭起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
    10. 模板方法模式: 在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
    11. 访问者模式:当你想要为一个对象的组合增加新的能力,且封装并不重要时,就使用访问者模式。
  1. 序列化,反序列化
  1. 序列化:**就是把变量从内存中变成可存储或可传输的过程。
  2. 反序列化:**就是把变量内容从序列化对象重新读到内存里。
  3. **pickle模块:**对于大多数应用程序来讲,dump()和load()函数的使用就是你使用pickle模块的全部了。
    + dumps(object)和dump(object):序列化。
    + loads(bytes)和load(bytes):反序列化。
    两者不同的是:dump()和load()是(反)序列化关于二进制文件中,dumps()和loads()是关于反序列化对象。
  4.  
    **json模块:**
    + json.dumps()从字典(可序列化json的对象)转换为json格式数据。
    + json.loads()从json到字典。
    + json.dump()和json.load()是file文件中使用的。
    + default:把任意一个对象变成一个可序列化为JSON的对象
    + intent:格式化规范点
  1.  python双下划线开头的方法,有什么用,为什么这么用
  1. **开头单下划线:**误认为它表示该方法或属性是该类型的私有方法或属性。但其实在Python中不存在真正意义上的私有方法或者属性,、
  2. 前面加单下划线“_”只是表示你不应该去访问这个方法或者属性,因为它不是API的一部分。单下划线“_”开始的成员变量叫保护变量,意思是只有类对象和子类对象能访问到这些变量。
  3. **开头双下划线:**将双下划线开头“__“理解为私有也不错。Python设计双膝划线开头的初衷和目的是为了避免子类覆盖父类的方法。双下划线“__”开始的是私有成员,意思是只有类对象自己能访问,连自对象也不能访问到这个数据。
  4. **头尾双下划线:**头尾双下划线“__xxx__”的方法是表示这是Python自己调用的,一般称这样的方法为魔术方法(magic methods)。比如len()函数求长度,其实它是后台调用了__len()__ 方法。这种机制使得我们可以在自己的类中覆写操作符。
  5. **尾下划线:**这是为了避免我们起的一些名字和Python保留关键字冲突,没有特殊含义。
  1. 多线程
  1. python提供了两个模块来实现多线程thread 和threading 
#coding=utf-8
import threading 
from time import sleep, ctime 
 
class MyThread(threading.Thread):

    def __init__(self,func,args,name=''):
        threading.Thread.__init__(self)
        self.name=name
        self.func=func
        self.args=args
    
    def run(self):
        apply(self.func,self.args)


def super_play(file,time):
    for i in range(2):
        print 'Start playing: %s! %s' %(file,ctime())
        sleep(time)


list = {'爱情买卖.mp3':3,'阿凡达.mp4':5}

#创建线程
threads = []
files = range(len(list))

for k,v in list.items():
    t = MyThread(super_play,(k,v),super_play.__name__)
    threads.append(t)        

if __name__ == '__main__': 
    #启动线程
    for i in files:
        threads[i].start() 
  for i in files:
      threads[i].join()

    #主线程
    print 'end:%s' %ctime()

  参考地址:

  1.  猴子补丁,是什么,怎么用
  1. 在运行时替换方法、属性等
  2. 在不修改第三方代码的情况下增加原来不支持的功能
  3. 在运行时为内存中的对象增加patch而不是在磁盘的源代码中增加
  4. 简单来说就是,用来在运行时动态修改已有的代码,而不需要修改原始代码。
  5. 猴子补丁在单元测试的时候有很好的用处
  1. PEP8规范
1、使用4个空格而不是tab键进行缩进。
2、每行长度不能超过80
3、使用空行来间隔函数和类,以及函数内部的大块代码
4、必要时候,在每一行下写注释
5、使用文档注释,写出函数注释
6、在操作符和逗号之后使用空格,但是不要在括号内部使用
7、命名类和函数的时候使用一致的方式,比如使用CamelCase来命名类,使用lower_case_with_underscores来命名函数和方法
8、在类中总是使用self来作为默认
9、尽量不要使用魔法方法
10、默认使用UTF-8,甚至ASCII作为编码方式
11、换行可以使用反斜杠,最好使用圆括号
12、不要在一句import中多个库

空格的使用:

各种右括号前不要加空格
逗号、冒号前不要加空格
函数的左括号前不要加空格。如Func(1)
序列的左括号前不要加空格。如list[2]
操作符左右各加一个空格,不要为了对齐增加空格
函数默认参数使用的赋值符左右省略空格
不要将多句语句写在同一行
if/for/while语句中,即使执行语句只有一句,也必须另起一行

 包名小写(不含下划线),函数名小写(可含下划线),常量名大写(可含下划线),类名驼峰写法,类属性小写(可含下划线)。
  1. python之禅,启发
import this

Beautiful is better than ugly.
# 优美胜于丑陋(Python以编写优美的代码为目标)
Explicit is better than implicit.
# 明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似) 
Simple is better than complex.
# 简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现) 
Complex is better than complicated.
# 复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)
Flat is better than nested.
# 扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套) 
Sparse is better than dense.
# 间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题) 
Readability counts.
# 可读性很重要(优美的代码是可读的) 
Special cases aren't special enough to break the rules.
Although practicality beats purity.
# 即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上) 
Errors should never pass silently.
Unless explicitly silenced.
# 不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写except:pass风格的代码) 
In the face of ambiguity, refuse the temptation to guess.
# 当存在多种可能,不要尝试去猜测 
There should be one-- and preferably only one --obvious way to do it.
# 而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法) 
Although that way may not be obvious at first unless you're Dutch.
# 虽然这并不容易,因为你不是 Python 之父(这里的Dutch是指Guido)
Now is better than never.
Although never is often better than *right* now.
# 做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
# 如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准) 
Namespaces are one honking great idea -- let's do more of those!
# 命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)
  1. 中间件,有哪些,写过没有
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

  Django中的中间键,可以自己定义中间件,定义的中间键要注册。

  • Linux基础部分
  1. 查看负载,负载的三个状态,负载能不能大于1
  1. 查看服务器负载有多种命令,w或者uptime都可以直接展示负载,
  2. load average分别对应于过去1分钟,5分钟,15分钟的负载平均值。
  3. 对一般的系统来说,根据cpu数量去判断。如果平均负载始终在1.2以下,而你有2颗cup的机器。那么基本不会出现cpu不够用的情况。也就是Load平均要小于Cpu的数量,一般是会根据15分钟那个load 平均值为首先。
  4. top 命令 
  5. 更多信息
  1. 查看内存占用
  1. top
  2. cat /proc/deminfo
  3. free -h 
  4. htop
  5. ps aux --sort -rss
  6. vmstart -a
  1. 查看网络/磁盘 I/O
  1. cat /proc/meminfo
  2. netstat
  3. 更多具体信息
  1. 查看磁盘地址
  1. df
  2. du
  3. fdisk
  4. 更多:
  1. 进程打开的最大数量
  1. ulimit -a
  2. LINUX中进程的最大理论数计算:
    每个进程的局部段描述表LDT都作为一个独立的段而存在,在全局段描述表GDT中要有一个表项指向这个段的起始地址,并说明该段的长度以及其他一些 参数。除上之外,每个进程还有一个TSS结构(任务状态段)也是一样。所以,每个进程都要在全局段描述表GDT中占据两个表项。那么,GDT的容量有多大 呢?段寄存器中用作GDT表下标的位段宽度是13位,所以GDT中可以有8192个描述项。除一些系统的开销(例如GDT中的第2项和第3项分别用于内核 的代码段和数据段,第4项和第5项永远用于当前进程的代码段和数据段,第1项永远是0,等等)以外,尚有8180个表项可供使用,所以理论上系统中最大的 进程数量是4090。
  1.  find命令,查看30天前的日志
  1. 详细信息
  1. 修改DNS
编辑 /etc/resolv.conf 
于是编辑 /etc/resolv.conf 
添加了两行(DNS地址是咨询了服务器运营商得知的) 
nameserver 202.96.209.133 
nameserver 61.129.88.123

再执行service network restart重启网络服务即可
  1. 计划任务
crond 是linux用来定期执行程序的命令。当安装完成操作系统之后,默认便会启动此任务调度命令。crond命令每分锺会定期检查是否有要执行的工作,如果有要执行的工作便会自动执行该工作。可以用以下的方法启动、关闭这个服务:

/sbin/service crond start //启动服务

/sbin/service crond stop //关闭服务

/sbin/service crond restart //重启服务

/sbin/service crond reload //重新载入配置
  1. 修改权限,777三个7的含义
Linux中可以用chmod修改文件的权限
Linux中每个文件都都有所有者、所有组、其他组。
Linux中的rwx也可以用数字表示

r=4

w=2

x=1
7=4+2+1及将rwx权限赋予所有者、组、其他用户
  1.  管道是什么,怎么用
  1. 匿名管道的的特性:
  • 用于有亲缘关系的进程
  • 半双工,单项通信,双向通信需要两个管道
  • 声明周期随进程
  • 有内置的同步互斥机制
  • 面向字节流
  1. 命名管道的特性除了可以使用在任意进程间外,其余的4条和匿名管道相同
  1.  打开日志的最后1000行数据
  1. tail -n 1000:显示最后1000行
  2. head -n 1000:显示前面1000行
  1.  vim的几种模式,光标怎么移动,复制,粘贴操作
  1. 基本上vi可以分为三种状态,分别是一般模式、编辑模式和命令行模式
  2. 移动光标
    【h、j、k、l】,分别控制光标左、下、上、右移一格
    按【ctrl+b】屏幕往"后"移动一页
    按【ctrl+f】屏幕往"前"移动一页 【n<space>】光标向右移动n个字符
    【Home】移动到这一行的最前面字符处:0数字,但不能用数字小键盘上的数字
    【End】 移动到这一行的最后面字符处:$,我测试好像不行
    【w】光标跳到下个字的开头
    【e】光标跳到下个字的字尾
    【H】 光标移动到这个屏幕的最上方那一行的第一个字符
    【M】 光标移动到这个屏幕的中间那一行的第一个字符
    【L】光标移动到这个屏幕的最下方那一行的第一个字符
    【G】 移动到这个文件的最后一行
    【nG】移动到这个文件的第n行(可配合:set nu)
    【gg】 移动到这个文件的第一行,相当于1G
    【n<Enter>】光标向下移动n行
  3. 删除、复制与粘贴
    【x】 为向后删除一个字符 (相当于【del】键)
    【X】 为向前删除一个字符(相当于【backspace】键)
    【nx】 连续向后删除n个字符
    【dd】 删除光标所在行
    【ndd】 删除光标所在的向下n行
    【d1G】 删除光标所在行到第一行的所有数据
    【dG】 删除光标所在到最后一行的所有数据
    【d$】 删除光标所在处,到该行的最后一个字符
    【d0】 删除光标所在处,到该行的最前一个字符
    【yy】 复制光标所在的那一行
    【nyy】 复制光标所在的向下n列
    【y1G】 复制光标所在行到第一行的所有数据
    【yG】 复制光标所在行到最后一行的所有数据
    【y0】 复制光标所在的那个字符到该行行首的所有数据
    【y$】 复制光标所在的那个字符到该行行尾的所有数据
    【p】将已复制的数据在光标下一行粘贴上
    【P】 则为贴在光标的上一行
    【u】 恢复前一个操作
    【Ctrl+r】重做上一个操作
    【.】 是重复前一个操作
  4. 查看更多:
  • 数据库相关
  1.  登录数据库,登录远程数据库
  1. mysql -h 192.168.5.116 -P 3306 -u root -p123456
  1. 创建用户,添加权限
  1. mysql> insert into mysql.user(Host,User,Password) values("localhost","test",password("1234"));
      这样就创建了一个名为:test 密码为:1234 的用户。
      注意:此处的"localhost",是指该用户只能在本地登录,不能在另外一台机器上远程登录。如果想远程登录的话,将"localhost"改为"%",表示在任何一台电脑上都可以登录。也可以指定某台机器可以远程登录。
    mysql> insert into mysql.user(Host,User,Password) values("localhost","test",password("1234"));
      这样就创建了一个名为:test 密码为:1234 的用户。
      注意:此处的"localhost",是指该用户只能在本地登录,不能在另外一台机器上远程登录。如果想远程登录的话,将"localhost"改为"%",表示在任何一台电脑上都可以登录。也可以指定某台机器可以远程登录。
  2. 为用户授权
      授权格式:grant 权限 on 数据库.* to 用户名@登录主机 identified by "密码"; 
      2.1 登录MYSQL(有ROOT权限),这里以ROOT身份登录:
      @>mysql -u root -p
      @>密码
      2.2 首先为用户创建一个数据库(testDB):
      mysql>create database testDB;
      2.3 授权test用户拥有testDB数据库的所有权限(某个数据库的所有权限):
       mysql>grant all privileges on testDB.* to test@localhost identified by '1234';
       mysql>flush privileges;//刷新系统权限表
      格式:grant 权限 on 数据库.* to 用户名@登录主机 identified by "密码"; 
      2.4 如果想指定部分权限给一用户,可以这样来写:
      mysql>grant select,update on testDB.* to test@localhost identified by '1234';
      mysql>flush privileges; //刷新系统权限表
      2.5 授权test用户拥有所有数据库的某些权限:   
      mysql>grant select,delete,update,create,drop on *.* to test@"%" identified by "1234";
         //test用户对所有数据库都有select,delete,update,create,drop 权限。
      //@"%" 表示对所有非本地主机授权,不包括localhost。(localhost地址设为127.0.0.1,如果设为真实的本地地址,不知道是否可以,没有验证。)
     //对localhost授权:加上一句grant all privileges on testDB.* to test@localhost identified by '1234';即可。
  3. 删除用户
       @>mysql -u root -p
      @>密码
       mysql>Delete FROM user Where User='test' and Host='localhost';
       mysql>flush privileges;
       mysql>drop database testDB; //删除用户的数据库
    删除账户及权限:>drop user 用户名@'%';
            >drop user 用户名@ localhost; 
  4. 修改指定用户密码
        @>mysql -u root -p
        @>密码
        mysql>update mysql.user set password=password('新密码') where User="test" and Host="localhost";
        mysql>flush privileges;
  1.  聚合函数
  1. 与分组相关的聚合函数
    count() 返回某个字段的值的行数
    max() 求最大某字段最大的值
    min() 求某字段最小值
    avg() 返回某字段平均值
    sum() 求某字段总数
    group_concat() 将分组的结果拼接成字符串
  1.  打开表,使用表,表结构
  1. 列出所有数据库
      mysql>show database;
  2. 切换数据库
      mysql>use '数据库名';
  3. 列出所有表
      mysql>show tables;
  4. 显示数据表结构
      mysql>describe 表名;
  5.  删除数据库和数据表
      mysql>drop database 数据库名;
      mysql>drop table 数据表名;
  1.  输出数据表中后50条数据
  1. select * from test_limit order by id DESC limit 50
  1.  group by 用法
  1. 根据给定列或者表达式的每一个不同的值将表中的行分成不同的组,使用组函数返回每一组的统计信息
  2. 规则:
      ①出现在SELECT子句中的单独的列,必须出现在GROUP BY子句中作为分组列
      ②分组列可以不出现在SELECT子句中
      ③分组列可出现在SELECT子句中的一个复合表达式中
      ④如果GROUP BY后面是一个复合表达式,那么在SELECT子句中,它必须整体作为一个表达式的一部分才能使用。
  • 其他
  1.  详述用户打开浏览器到收到页面的过程
  1. 三次握手,四次挥手。
  1.  每天学习的过程
  1. 根据自己的学习情况回答。
  1.  以后打算用python干什么
  1. 考察对python用法的理解。