数据结构 各种查找算法

CD-Python-JY-1809班项目阶段教学内容

开篇 - 就业形势分析

  1. 就业方向

    • Python后端开发工程师(Python基础、Django、Flask、Tornado、Sanic、RESTful、MySQL、Redis、MongoDB、ElasticSearch/Solr)
      • Web应用服务器 / 游戏后端服务器 / 移动端数据接口 / 系统支撑平台
    • Python爬虫开发工程师(Python基础、常用标准库和三方库、Scrapy/PySpider、Selenium/Appium、Redis、MySQL/MongoDB、前端相关知识、HTTP(S)、TCP/IP、Charles/Fiddler/Wireshark)
    • Python量化交易开发工程师(扎实的Python功底、数据结构和算法、金融知识、数字货币)
    • Python数据分析工程师(Python基础、NumPy/SciPy、Pandas、Matplotlib、机器学习算法)
    • Python自动化测试工程师(Python基础、软件测试基础、Linux、Shell、Selenium / Robot Framework、JMeter / LoadRunner / QTP、CI)
    • Python自动化运维工程师(Python基础、Linux、Shell、Docker、paramiko、Fabric、Ansible、Saltstack、Puppet、PlayBook、Zabbix)
    • Python云平台开发工程师(扎实的Python功底、OpenStack、CloudStack、Ovirt、KVM、微服务架构、Docker、K8S)
  2. 面试加分项

    • 有自己的Github开源项目和博客。

    • 有分布式项目/微服务架构相关经验。(Nginx、LVS、Keepalived、Zookeeper、Docker)

    • 有项目性能调优和安全相关经验。(AB、WebBench、SysBench、JMeter、LoadRunner、QTP)

    • 有使用行业工具和中间件的经验。(Redis、FastDFS、RabbitMQ、Zabbix、Ansible、Nagios、ElasticSearch/Solr)

    • 熟悉前端开发相关的知识。(jQuery、Bootstrap、Vue.js、AngularJS、React)

    • 有其他语言开发经验(项目技术栈迁移能力)。(Java、C/C++)

    • 有大数据开发相关经验。(HDFS、YARN、MapReduce、HBase、Hive、Mahout、Pig、Spark、ZooKeeper)

      [图片上传失败...(image-cc06ef-1558321309426)]

第01-03天:白板编程练习

所谓白板编程练习就是在纸上写代码,这个是大多数面试的必要环节,也是最容易被忽略的东西。下面罗列的内容是面试的笔试环节中出现频率较高的问题,同时对相关知识点进行了梳理。

  1. 数据结构和算法

    • 算法:解决问题的方法和步骤

    • 评价算法的好坏:渐近时间复杂度和渐近空间复杂度。

    • 渐近时间复杂度的大O标记:

      • - 常量时间复杂度 - 布隆过滤器 / 哈希存储
      • - 对数时间复杂度 - 折半查找(二分查找)
      • - 线性时间复杂度 - 顺序查找 / 桶排序
      • - 对数线性时间复杂度 - 高级排序算法(归并排序、快速排序)
      • - 平方时间复杂度 - 简单排序算法(选择排序、插入排序、冒泡排序)
      • - 立方时间复杂度 - Floyd算法 / 矩阵乘法运算
      • - 几何级数时间复杂度 - 汉诺塔
      • - 阶乘时间复杂度 - 旅行经销商问题 - NP

      [图片上传失败...(image-baa54a-1558321309426)]

      [图片上传失败...(image-146654-1558321309426)]

    • 排序算法(选择、冒泡和归并)和查找算法(顺序和折半)

      def select_sort(origin_items, comp=lambda x, y: x < y):
          """简单选择排序"""
          items = origin_items[:]
          for i in range(len(items) - 1):
              min_index = i
              for j in range(i + 1, len(items)):
                  if comp(items[j], items[min_index]):
                      min_index = j
              items[i], items[min_index] = items[min_index], items[i]
          return items
      
      def bubble_sort(origin_items, comp=lambda x, y: x > y):
          """高质量冒泡排序(搅拌排序)"""
          items = origin_items[:]
          for i in range(len(items) - 1):
              swapped = False
              for j in range(i, len(items) - 1 - i):
                  if comp(items[j], items[j + 1]):
                      items[j], items[j + 1] = items[j + 1], items[j]
                      swapped = True
              if swapped:
                  swapped = False
                  for j in range(len(items) - 2 - i, i, -1):
                      if comp(items[j - 1], items[j]):
                          items[j], items[j - 1] = items[j - 1], items[j]
                          swapped = True
              if not swapped:
                  break
          return items
      
      def merge_sort(items, comp=lambda x, y: x <= y):
          """归并排序(分治法)"""
          if len(items) < 2:
              return items[:]
          mid = len(items) // 2
          left = merge_sort(items[:mid], comp)
          right = merge_sort(items[mid:], comp)
          return merge(left, right, comp)
      
      
      def merge(items1, items2, comp):
          """合并(将两个有序的列表合并成一个有序的列表)"""
          items = []
          index, index2 = 0, 0
          while index1 < len(items1) and index2 < len(items2):
              if comp(items1[index1], items2[index2]):
                  items.append(items1[index1])
                  index1 += 1
              else:
                  items.append(items2[index2])
                  index2 += 1
          items += items1[index1:]
          items += items2[index2:]
          return items
      
      def seq_search(items, key):
          """顺序查找"""
          for index, item in enumerate(items):
              if item == key:
                  return index
          return -1
      
      def bin_search(items, key):
          """折半查找"""
          start, end = 0, len(items) - 1
          while start <= end:
              mid = (start + end) // 2
              if key > items[mid]:
                  start = mid + 1
              elif key < items[mid]:
                  end = mid - 1
              else:
                  return mid
          return -1
      
    • 使用生成式(推导式)语法生成列表、集合和字典。

      例子1:将一个句子中每个单词放到列表中且每个单词首字母大写。

      sentence = 'i love this world'
      [x.capitalize() for x in sentence.split()]
      

      例子2:用字典中股票价格大于100元的股票构造一个新的字典。

      prices = {
          'AAPL': 191.88,
          'GOOG': 1186.96,
          'IBM': 149.24,
          'ORCL': 48.44,
          'ACN': 166.89,
          'FB': 208.09,
          'SYMC': 21.29
      }
      prices2 = {key: value for key, value in prices.items() if value > 100}
      print(prices2)
      

      例子3:嵌套的列表 - 通过列表保存多个学生多门课程的成绩。

      names = ['关羽', '张飞', '赵云', '马超', '黄忠']
      courses = ['语文', '数学', '英语']
      # 录入五个学生三门课程的成绩
      # 错误的做法 - 参考http://pythontutor.com/visualize.html#mode=edit
      # scores = [[0] * len(courses)] * len(names)
      # 正确的做法
      scores = [[0] * len(courses) for _ in range(len(names))]
      for row, name in enumerate(names):
          for col, course in enumerate(courses):
              scores[row][col] = float(input(f'请输入{name}的{course}成绩: '))
              print(scores)
      

      Python Tutor - VISUALIZE CODE AND GET LIVE HELP

    • heapq(优先队列)、itertools(迭代工具)等的用法

      """
      从列表中找出最大的或最小的N个元素
      """
      import heapq
      
      list1 = [34, 25, 12, 99, 87, 63, 58, 78, 88, 92]
      list2 = [
          {'name': 'IBM', 'shares': 100, 'price': 91.1},
          {'name': 'AAPL', 'shares': 50, 'price': 543.22},
          {'name': 'FB', 'shares': 200, 'price': 21.09},
          {'name': 'HPQ', 'shares': 35, 'price': 31.75},
          {'name': 'YHOO', 'shares': 45, 'price': 16.35},
          {'name': 'ACME', 'shares': 75, 'price': 115.65}
      ]
      print(heapq.nlargest(3, list1))
      print(heapq.nsmallest(3, list1))
      print(heapq.nlargest(2, list2, key=lambda x: x['price']))
      print(heapq.nlargest(2, list2, key=lambda x: x['shares']))
      
      """
      迭代工具 - 排列 / 组合 / 笛卡尔积
      """
      import itertools
      
      itertools.permutations('ABCD')
      itertools.combinations('ABCDE', 3)
      itertools.product('ABCD', '123')
      
    • collections模块下的高性能容器

      • deque:与list类似,但底层基于双向链表实现。当需要在中间或头部插入元素时,deque比list快得多;当需要进行随机访问时,deque比list要慢。
      • defaultdict:与dict类似,但是可以为新的键指定默认值的创建工厂,避免编写额外的代码来初始化键值对,比dict的setdefault方法更为高效。
      • namedtuple:与元组类似,但是可以为每个成员指定名字。
      from collections import namedtuple
      
      
      Card = namedtuple('Card', ['suite', 'face'])
      card = Card('红桃', 5)
      print(card.suite, card.face)
      
      """
      找出序列中出现次数最多的元素 - Counter类
      """
      from collections import Counter
      
      words = [
          'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
          'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around',
          'the', 'eyes', "don't", 'look', 'around', 'the', 'eyes',
          'look', 'into', 'my', 'eyes', "you're", 'under'
      ]
      counter = Counter(words)
      print(counter.most_common(3))
      
      """
      可以指定元素顺序的字典 - OrderedDict 
      """
      from collections import OrderedDict
      
      
      fruits = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
      print(OrderedDict(sorted(fruits.items(), key=lambda x: x[0])))
      print(OrderedDict(sorted(fruits.items(), key=lambda x: x[1])))
      print(OrderedDict(sorted(fruits.items(), key=lambda x: len(x[0]))))
      
    • 常用算法:

      • 穷举法 - 又称为暴力破解法,对所有的可能性进行验证,直到找到正确答案。
      • 贪婪法 - 在对问题求解时,总是做出在当前看来是最好的选择,不追求最优解,快速找到满意解。
      • 分治法 - 把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题,直到可以直接求解的程度,最后将子问题的解进行合并得到原问题的解。
      • 回溯法 - 回溯法又称为试探法,按选优条件向前搜索,当搜索到某一步发现原先选择并不优或达不到目标时,就退回一步重新选择。
      • 动态规划 - 基本思想也是将待求解问题分解成若干个子问题,先求解并保存这些子问题的解,避免产生大量的重复运算。

      穷举法例子:百钱百鸡和五人分鱼。

      # 公鸡5元一只 母鸡3元一只 小鸡1元三只
      # 用100元买100只鸡 问公鸡/母鸡/小鸡各多少只
      for x in range(20):
          for y in range(33):
              z = 100 - x - y
              if 5 * x + 3 * y + z // 3 == 100 and z % 3 == 0:
                  print(x, y, z)
      
      # A、B、C、D、E五人在某天夜里合伙捕鱼 最后疲惫不堪各自睡觉
      # 第二天A第一个醒来 他将鱼分为5份 扔掉多余的1条 拿走自己的一份
      # B第二个醒来 也将鱼分为5份 扔掉多余的1条 拿走自己的一份
      # 然后C、D、E依次醒来也按同样的方式分鱼 问他们至少捕了多少条鱼
      fish = 1
      while True:
          total = fish
          enough = True
          for _ in range(5):
              if (total - 1) % 5 == 0:
                  total = (total - 1) // 5 * 4
              else:
                  enough = False
                  break
          if enough:
              print(fish)
              break
          fish += 1
      

      贪婪法例子:假设小偷有一个背包,最多能装20公斤赃物,他闯入一户人家,发现如下表所示的物品。很显然,他不能把所有物品都装进背包,所以必须确定拿走哪些物品,留下哪些物品。

      名称 价格(美元) 重量(kg)
      电脑 200 20
      收音机 20 4
      175 10
      花瓶 50 2
      10 1
      油画 90 9
      """
      贪婪法:在对问题求解时,总是做出在当前看来是最好的选择,不追求最优解,快速找到满意解。
      输入:
      20 6
      电脑 200 20
      收音机 20 4
      钟 175 10
      花瓶 50 2
      书 10 1
      油画 90 9
      """
      class Thing(object):
          """物品"""
      
          def __init__(self, name, price, weight):
              self.name = name
              self.price = price
              self.weight = weight
      
          @property
          def value(self):
              """价格重量比"""
              return self.price / self.weight
      
      
      def input_thing():
          """输入物品信息"""
          name_str, price_str, weight_str = input().split()
          return name_str, int(price_str), int(weight_str)
      
      
      def main():
          """主函数"""
          max_weight, num_of_things = map(int, input().split())
          all_things = []
          for _ in range(num_of_things):
              all_things.append(Thing(*input_thing()))
          all_things.sort(key=lambda x: x.value, reverse=True)
          total_weight = 0
          total_price = 0
          for thing in all_things:
              if total_weight + thing.weight <= max_weight:
                  print(f'小偷拿走了{thing.name}')
                  total_weight += thing.weight
                  total_price += thing.price
          print(f'总价值: {total_price}美元')
      
      
      if __name__ == '__main__':
          main()
      

      分治法例子:快速排序。

      """
      快速排序 - 选择枢轴对元素进行划分,左边都比枢轴小右边都比枢轴大
      """
      def quick_sort(origin_items, comp=lambda x, y: x <= y):
          items = origin_items[:]
          _quick_sort(items, 0, len(items) - 1, comp)
          return items
      
      
      def _quick_sort(items, start, end, comp):
          if start < end:
              pos = _partition(items, start, end, comp)
              _quick_sort(items, start, pos - 1, comp)
              _quick_sort(items, pos + 1, end, comp)
      
      
      def _partition(items, start, end, comp):
          pivot = items[end]
          i = start - 1
          for j in range(start, end):
              if comp(items[j], pivot):
                  i += 1
                  items[i], items[j] = items[j], items[i]
          items[i + 1], items[end] = items[end], items[i + 1]
          return i + 1
      

      回溯法例子:骑士巡逻。

      """
      递归回溯法:叫称为试探法,按选优条件向前搜索,当搜索到某一步,发现原先选择并不优或达不到目标时,就退回一步重新选择,比较经典的问题包括骑士巡逻、八皇后和迷宫寻路等。
      """
      import sys
      import time
      
      SIZE = 5
      total = 0
      
      
      def print_board(board):
          for row in board:
              for col in row:
                  print(str(col).center(4), end='')
              print()
      
      
      def patrol(board, row, col, step=1):
          if row >= 0 and row < SIZE and \
              col >= 0 and col < SIZE and \
              board[row][col] == 0:
              board[row][col] = step
              if step == SIZE * SIZE:
                  global total
                  total += 1
                  print(f'第{total}种走法: ')
                  print_board(board)
              patrol(board, row - 2, col - 1, step + 1)
              patrol(board, row - 1, col - 2, step + 1)
              patrol(board, row + 1, col - 2, step + 1)
              patrol(board, row + 2, col - 1, step + 1)
              patrol(board, row + 2, col + 1, step + 1)
              patrol(board, row + 1, col + 2, step + 1)
              patrol(board, row - 1, col + 2, step + 1)
              patrol(board, row - 2, col + 1, step + 1)
              board[row][col] = 0
      
      
      def main():
          board = [[0] * SIZE for _ in range(SIZE)]
          patrol(board, SIZE - 1, SIZE - 1)
      
      
      if __name__ == '__main__':
          main()
      

      动态规划例子1:斐波拉切数列。(不使用动态规划将会是几何级数复杂度)

      """
      动态规划 - 适用于有重叠子问题和最优子结构性质的问题
      使用动态规划方法所耗时间往往远少于朴素解法(用空间换取时间)
      """
      def fib(num, temp={}):
          """用递归计算Fibonacci数"""
          if num in (1, 2):
              return 1
          try:
              return temp[num]
          except KeyError:
              temp[num] = fib(num - 1) + fib(num - 2)
              return temp[num]
      
      """
      Python中的functools模块有一个lru_cache装饰器,也可以做类似的事情
      如果愿意也可以自己写一个类似的装饰器来做同样的事情,大家可以尝试一下
      """
      from functools import lru_cache
      
      
      @lru_cache(maxsize=None)
      def fib(num):
          if num in (1, 2):
              return 1
          return fib(num - 1) + fib(num - 2)
      
      
      # 查看缓存命中次数
      # CacheInfo(hits=237, misses=120, maxsize=None, currsize=120)
      fib.cache_info()
      

      动态规划例子2:子列表元素之和的最大值。(使用动态规划可以避免二重循环)

      说明:子列表指的是列表中索引(下标)连续的元素构成的列表;列表中的元素是int类型,可能包含正整数、0、负整数;程序输入列表中的元素,输出子列表元素求和的最大值,例如:

      输入:1 -2 3 5 -3 2

      输出:8

      输入:0 -2 3 5 -1 2

      输出:9

      输入:-9 -2 -3 -5 -3

      输出:-2

      def main():
          items = list(map(int, input().split()))
          size = len(items)
          overall, partial = {}, {}
          overall[size - 1] = partial[size - 1] = items[size - 1]
          for i in range(size - 2, -1, -1):
              partial[i] = max(items[i], partial[i + 1] + items[i])
              overall[i] = max(partial[i], overall[i + 1])
          print(overall[0])
      
      
      if __name__ == '__main__':
          main()
      
  2. 函数的使用方式

    • 将函数视为“一等公民”

      • 函数可以赋值给变量
      • 函数可以作为函数的参数
      • 函数可以作为函数的返回值
    • 高阶函数的用法(filtermap以及它们的替代品)

      items1 = list(map(lambda x: x ** 2, filter(lambda x: x % 2, range(1, 10))))
      items2 = [x ** 2 for x in range(1, 10) if x % 2]
      
    • 位置参数、可变参数、关键字参数、命名关键字参数

    • 参数的元信息(代码可读性问题)

    • 匿名函数和内联函数的用法(lambda函数)

      例子:一行代码实现从m到n的整数()求和。

      (lambda m, n: functools.reduce(int.__add__, range(m, n + 1)))(1, 100)
      

      例子:一行代码实现求阶乘。

      (lambda num: functools.reduce(int.__mul__, range(1, num + 1), 1))(5)
      
    • 闭包和作用域问题

      • Python搜索变量的LEGB顺序(LocalEmbeddedGlobalBuilt-in)

      • globalnonlocal关键字的作用

        global:声明或定义全局变量(要么直接使用现有的全局作用域的变量,要么定义一个变量放到全局作用域)。

        nonlocal:声明使用嵌套作用域的变量(嵌套作用域必须存在该变量,否则报错)。

    • 装饰器函数(使用装饰器和取消装饰器)

      例子:输出函数执行时间的装饰器。

      def record_time(func):
          """自定义装饰函数的装饰器"""
          
          @wraps(func)
          def wrapper(*args, **kwargs):
              start = time()
              result = func(*args, **kwargs)
              print(f'{func.__name__}: {time() - start}秒')
              return result
              
          return wrapper
      

      如果装饰器不希望跟print函数耦合,可以编写带参数的装饰器。

      from functools import wraps
      from time import time
      
      
      def record(output):
          """自定义带参数的装饰器"""
         
         def decorate(func):
             
             @wraps(func)
             def wrapper(*args, **kwargs):
                 start = time()
                 result = func(*args, **kwargs)
                 output(func.__name__, time() - start)
                 return result
                  
             return wrapper
         
         return decorate
      
      from functools import wraps
      from time import time
      
      
      class Record():
          """自定义装饰器类(通过__call__魔术方法使得对象可以当成函数调用)"""
      
          def __init__(self, output):
              self.output = output
      
          def __call__(self, func):
      
              @wraps(func)
              def wrapper(*args, **kwargs):
                  start = time()
                  result = func(*args, **kwargs)
                  self.output(func.__name__, time() - start)
                  return result
      
              return wrapper
      

      说明:由于对带装饰功能的函数添加了@wraps装饰器,可以通过func.__wrapped__方式获得被装饰之前的函数或类来取消装饰器的作用。

      例子:用装饰器来实现单例模式。

      from functools import wraps
      
      
      def singleton(cls):
          """装饰类的装饰器"""
          instances = {}
      
          @wraps(cls)
          def wrapper(*args, **kwargs):
              if cls not in instances:
                  instances[cls] = cls(*args, **kwargs)
              return instances[cls]
      
          return wrapper
      
      
      @singleton
      class President():
          """总统(单例类)"""
          pass
      

      说明:上面的代码中用到了闭包(closure),不知道你是否已经意识到了。还没有一个小问题就是,上面的代码并没有实现线程安全的单例,如果要实现线程安全的单例应该怎么做呢?

      from functools import wraps
      
      
      def singleton(cls):
          """线程安全的单例装饰器"""
          instances = {}
          locker = Lock()
      
          @wraps(cls)
          def wrapper(*args, **kwargs):
              if cls not in instances:
                  with locker:
                      if cls not in instances:
                          instances[cls] = cls(*args, **kwargs)
              return instances[cls]
      
          return wrapper
      
  3. 面向对象相关知识

    • 三大支柱:封装、继承、多态

      例子:工资结算系统。

      """
      月薪结算系统 - 部门经理每月15000 程序员每小时200 销售员1800底薪加销售额5%提成
      """
      from abc import ABCMeta, abstractmethod
      
      
      class Employee(metaclass=ABCMeta):
          """员工(抽象类)"""
      
          def __init__(self, name):
              self.name = name
      
          @abstractmethod
          def get_salary(self):
              """结算月薪(抽象方法)"""
              pass
      
      
      class Manager(Employee):
          """部门经理"""
      
          def get_salary(self):
              return 15000.0
      
      
      class Programmer(Employee):
          """程序员"""
      
          def __init__(self, name, working_hour=0):
              self.working_hour = working_hour
              super().__init__(name)
      
          def get_salary(self):
              return 200.0 * self.working_hour
      
      
      class Salesman(Employee):
          """销售员"""
      
          def __init__(self, name, sales=0.0):
              self.sales = sales
              super().__init__(name)
      
          def get_salary(self):
              return 1800.0 + self.sales * 0.05
      
      
      emp_types = {'M': Manager, 'P': Programmer, 'S': Salesman}
      
      
      class EmployeeFactory(object):
          """创建员工的工厂(工厂模式 - 通过工厂实现对象使用者和对象之间的解耦合)"""
      
          @staticmethod
          def create(emp_type, *args, **kwargs):
              """创建员工"""
              emp = None
              if emp_type in emp_types:
                  emp = emp_types[emp_type](*args, **kwargs)
              return emp
      
      if __name__ == '__main__':
          emps = [
              EmployeeFactory.create('M', '曹操'), 
              EmployeeFactory.create('P', '荀彧', 120),
              EmployeeFactory.create('P', '郭嘉', 85), 
              EmployeeFactory.create('S', '典韦', 123000),
          ]
          for emp in emps:
              print('%s: %.2f元' % (emp.name, emp.get_salary()))
      
    • 类与类之间的关系

      • is-a关系:继承
      • has-a关系:关联 / 聚合 / 合成
      • use-a关系:依赖
    • 对象的复制(深复制/深拷贝/深度克隆和浅复制/浅拷贝/影子克隆)

      from copy import copy, deepcopy
      
      items0 = [1, [2, 3], [[4, 5, 6], [7, 8, 9]]]
      
      # 看看下面这些输出前后两个值是否相等
      items1 = items0
      print(id(items0), id(items1))
      
      items2 = items1[:]
      print(id(items1), id(items2))
      print(id(items1[0]), id(items2[0]))
      print(id(items1[1]), id(items2[1]))
      print(id(items1[2][0]), id(items2[2][0]))
      print('-' * 25) 
      
      items3 = copy(items1)
      print(id(items1), id(items3))
      print(id(items1[0]), id(items3[0]))
      print(id(items1[1]), id(items3[1]))
      print(id(items1[2][0]), id(items3[2][0]))
      print('-' * 25) 
      
      items4 = deepcopy(items1)
      print(id(items1), id(items4))
      print(id(items1[0]), id(items4[0]))
      print(id(items1[1]), id(items4[1]))
      print(id(items1[2][0]), id(items4[2][0]))
      
    • 垃圾回收、循环引用和弱引用

      Python使用了自动化内存管理,这种管理机制以引用计数为基础,同时也引入了标记-清除分代收集两种机制为辅的策略。

      typedef struct_object {
          /* 引用计数 */
          int ob_refcnt;
          /* 对象指针 */
          struct_typeobject *ob_type;
      } PyObject;
      
      /* 增加引用计数的宏定义 */
      #define Py_INCREF(op)   ((op)->ob_refcnt++)
      /* 减少引用计数的宏定义 */
      #define Py_DECREF(op) \ //减少计数
          if (--(op)->ob_refcnt != 0) \
              ; \
          else \
              __Py_Dealloc((PyObject *)(op))
      

      导致引用计数+1的情况:

      • 对象被创建,例如a = 23
      • 对象被引用,例如b = a
      • 对象被作为参数,传入到一个函数中,例如f(a)
      • 对象作为一个元素,存储在容器中,例如list1 = [a, a]

      导致引用计数-1的情况:

      • 对象的别名被显式销毁,例如del a
      • 对象的别名被赋予新的对象,例如a = 24
      • 一个对象离开它的作用域,例如f函数执行完毕时,f函数中的局部变量(全局变量不会)
      • 对象所在的容器被销毁,或从容器中删除对象

      引用计数可能会导致循环引用问题,而循环引用会导致内存泄露,如下面的代码所示。为了解决这个问题,Python中引入了“标记-清除”和“分代收集”。在创建一个对象的时候,对象被放在第一代中,如果在第一代的垃圾检查中对象存活了下来,该对象就会被放到第二代中,同理在第二代的垃圾检查中对象存活下来,该对象就会被放到第三代中。

      # 循环引用会导致内存泄露 - Python除了引用技术还引入了标记清理和分代回收
      # 在Python 3.6以前如果重写__del__魔术方法会导致循环引用处理失效
      # 如果不想造成循环引用可以使用弱引用
      list1 = []
      list2 = [] 
      list1.append(list2)
      list2.append(list1)
      

      以下情况会导致垃圾回收:

      • 调用gc.collect()
      • gc模块的计数器达到阀值
      • 程序退出

      如果循环引用中两个对象都定义了__del__方法,gc模块不会销毁这些不可达对象,因为gc模块不知道应该先调用哪个对象的__del__方法,这个问题在Python 3.6中得到了解决。

      也可以通过weakref模块构造弱引用的方式来解决循环引用的问题。

    • 魔法属性和方法(请参考《Python魔法方法指南》)

      有几个小问题请大家思考:

      • 自定义的对象能不能使用运算符做运算?
      • 自定义的对象能不能放到set中?能去重吗?
      • 自定义的对象能不能作为dict的键?
      • 自定义的对象能不能使用上下文语法?
    • 混入(Mixin)

      例子:自定义字典限制只有在指定的key不存在时才能在字典中设置键值对。

      class SetOnceMappingMixin():
          """自定义混入类"""
          __slots__ = ()
      
          def __setitem__(self, key, value):
              if key in self:
                  raise KeyError(str(key) + ' already set')
              return super().__setitem__(key, value)
      
      
      class SetOnceDict(SetOnceMappingMixin, dict):
          """自定义字典"""
          pass
      
      
      my_dict= SetOnceDict()
      try:
          my_dict['username'] = 'jackfrued'
          my_dict['username'] = 'hellokitty'
      except KeyError:
          pass
      print(my_dict)
      
    • 元编程和元类

      例子:用元类实现单例模式。

      import threading
      
      
      class SingletonMeta(type):
          """自定义元类"""
      
          def __init__(cls, *args, **kwargs):
              cls.__instance = None
              cls.__lock = threading.Lock()
              super().__init__(*args, **kwargs)
      
          def __call__(cls, *args, **kwargs):
              if cls.__instance is None:
                  with cls.__lock:
                      if cls.__instance is None:
                          cls.__instance = super().__call__(*args, **kwargs)
              return cls.__instance
      
      
      class President(metaclass=SingletonMeta):
          """总统(单例类)"""
          pass
      
    • 面向对象设计原则

      • 单一职责原则 (SRP)- 一个类只做该做的事情(类的设计要高内聚)
      • 开闭原则 (OCP)- 软件实体应该对扩展开发对修改关闭
      • 依赖倒转原则(DIP)- 面向抽象编程(在弱类型语言中已经被弱化)
      • 里氏替换原则(LSP) - 任何时候可以用子类对象替换掉父类对象
      • 接口隔离原则(ISP)- 接口要小而专不要大而全(Python中没有接口的概念)
      • 合成聚合复用原则(CARP) - 优先使用强关联关系而不是继承关系复用代码
      • 最少知识原则(迪米特法则,LoD)- 不要给没有必然联系的对象发消息

      说明:上面加粗的字母放在一起称为面向对象的SOLID原则。

    • GoF设计模式

      • 创建型模式:单例、工厂、建造者、原型
      • 结构型模式:适配器、门面(外观)、代理
      • 行为型模式:迭代器、观察者、状态、策略

      例子:可插拔的哈希算法。

      class StreamHasher():
          """哈希摘要生成器(策略模式)"""
      
          def __init__(self, alg='md5', size=4096):
              self.size = size
              alg = alg.lower()
              self.hasher = getattr(__import__('hashlib'), alg.lower())()
      
          def __call__(self, stream):
              return self.to_digest(stream)
      
          def to_digest(self, stream):
              """生成十六进制形式的摘要"""
              for buf in iter(lambda: stream.read(self.size), b''):
                  self.hasher.update(buf)
              return self.hasher.hexdigest()
      
      
      def main():
          """主函数"""
          hasher1 = StreamHasher()
          with open('Python-3.7.1.tgz', 'rb') as stream:
              print(hasher1.to_digest(stream))
          hasher2 = StreamHasher('sha1')
          with open('Python-3.7.1.tgz', 'rb') as stream:
              print(hasher2(stream))
      
      
      if __name__ == '__main__':
          main()
      
  4. 迭代器和生成器

    • 和迭代器相关的魔术方法(__iter____next__

    • 两种创建生成器的方式(生成器表达式和yield关键字)

      def fib(num):
          """生成器"""
          a, b = 0, 1
          for _ in range(num):
              a, b = b, a + b
              yield a
         
         
      class Fib(object):
          """迭代器"""
          
          def __init__(self, num):
              self.num = num
              self.a, self.b = 0, 1
              self.idx = 0
         
          def __iter__(self):
              return self
      
          def __next__(self):
              if self.idx < self.num:
                  self.a, self.b = self.b, self.a + self.b
                  self.idx += 1
                  return self.a
              raise StopIteration()
      
  5. 并发编程

    Python中实现并发编程的三种方案:多线程、多进程和异步I/O。并发编程的好处在于可以提升程序的执行效率以及改善用户体验;坏处在于并发的程序不容易开发和调试,同时对其他程序来说它并不友好。

    • 多线程:Python中提供了Thread类并辅以Lock、Condition、Event、Semaphore和Barrier。Python中有GIL来防止多个线程同时执行本地字节码,这个锁对于CPython是必须的,因为CPython的内存管理并不是线程安全的,因为GIL的存在多线程并不能发挥CPU的多核特性。

      """
      面试题:进程和线程的区别和联系?
      进程 - 操作系统分配内存的基本单位 - 一个进程可以包含一个或多个线程
      线程 - 操作系统分配CPU的基本单位
      并发编程(concurrent programming)
      1. 提升执行性能 - 让程序中没有因果关系的部分可以并发的执行
      2. 改善用户体验 - 让耗时间的操作不会造成程序的假死
      """
      import glob
      import os
      import threading
      
      from PIL import Image
      
      PREFIX = 'thumbnails'
      
      
      def generate_thumbnail(infile, size, format='PNG'):
          """生成指定图片文件的缩略图"""
         file, ext = os.path.splitext(infile)
         file = file[file.rfind('/') + 1:]
         outfile = f'{PREFIX}/{file}_{size[0]}_{size[1]}.{ext}'
         img = Image.open(infile)
         img.thumbnail(size, Image.ANTIALIAS)
         img.save(outfile, format)
      
      
      def main():
          """主函数"""
         if not os.path.exists(PREFIX):
             os.mkdir(PREFIX)
         for infile in glob.glob('images/*.png'):
             for size in (32, 64, 128):
                  # 创建并启动线程
                 threading.Thread(
                     target=generate_thumbnail, 
                     args=(infile, (size, size))
                 ).start()
                 
      
      if __name__ == '__main__':
         main()
      

      多个线程竞争资源的情况

      """
      多线程程序如果没有竞争资源处理起来通常也比较简单
      当多个线程竞争临界资源的时候如果缺乏必要的保护措施就会导致数据错乱
      说明:临界资源就是被多个线程竞争的资源
      """
      import time
      import threading
      
      from concurrent.futures import ThreadPoolExecutor
      
      
      class Account(object):
          """银行账户"""
      
          def __init__(self):
              self.balance = 0.0
              self.lock = threading.Lock()
      
          def deposit(self, money):
              # 通过锁保护临界资源
              with self.lock:
                  new_balance = self.balance + money
                  time.sleep(0.001)
                  self.balance = new_balance
      
      
      class AddMoneyThread(threading.Thread):
          """自定义线程类"""
      
          def __init__(self, account, money):
              self.account = account
              self.money = money
              # 自定义线程的初始化方法中必须调用父类的初始化方法
              super().__init__()
      
          def run(self):
              # 线程启动之后要执行的操作
              self.account.deposit(self.money)
      
      def main():
          """主函数"""
          account = Account()
          # 创建线程池
          pool = ThreadPoolExecutor(max_workers=10)
          futures = []
          for _ in range(100):
              # 创建线程的第1种方式
              # threading.Thread(
              #     target=account.deposit, args=(1, )
              # ).start()
              # 创建线程的第2种方式
              # AddMoneyThread(account, 1).start()
              # 创建线程的第3种方式
              # 调用线程池中的线程来执行特定的任务
              future = pool.submit(account.deposit, 1)
              futures.append(future)
          # 关闭线程池
          pool.shutdown()
          for future in futures:
              future.result()
          print(account.balance)
      
      
      if __name__ == '__main__':
          main()
      

      修改上面的程序,启动5个线程向账户中存钱,5个线程从账户中取钱,取钱时如果余额不足就暂停线程进行等待。为了达到上述目标,需要对存钱和取钱的线程进行调度,在余额不足时取钱的线程暂停并释放锁,而存钱的线程将钱存入后要通知取钱的线程,使其从暂停状态被唤醒。可以使用threading模块的Condition来实现线程调度,该对象也是基于锁来创建的,代码如下所示:

      """
      多个线程竞争一个资源 - 保护临界资源 - 锁(Lock/RLock)
      多个线程竞争多个资源(线程数>资源数) - 信号量(Semaphore)
      多个线程的调度 - 暂停线程执行/唤醒等待中的线程 - Condition
      """
      from concurrent.futures import ThreadPoolExecutor
      from random import randint
      from time import sleep
      
      import threading
      
      
      class Account():
          """银行账户"""
      
          def __init__(self, balance=0):
              self.balance = balance
              lock = threading.Lock()
              self.condition = threading.Condition(lock)
      
          def withdraw(self, money):
              """取钱"""
              with self.condition:
                  while money > self.balance:
                      self.condition.wait()
                  new_balance = self.balance - money
                  sleep(0.001)
                  self.balance = new_balance
      
          def deposit(self, money):
              """存钱"""
              with self.condition:
                  new_balance = self.balance + money
                  sleep(0.001)
                  self.balance = new_balance
                  self.condition.notify_all()
      
      
      def add_money(account):
          while True:
              money = randint(5, 10)
              account.deposit(money)
              print(threading.current_thread().name, 
                    ':', money, '====>', account.balance)
              sleep(0.5)
      
      
      def sub_money(account):
          while True:
              money = randint(10, 30)
              account.withdraw(money)
              print(threading.current_thread().name, 
                    ':', money, '<====', account.balance)
              sleep(1)
      
      
      def main():
          account = Account()
          with ThreadPoolExecutor(max_workers=10) as pool:
              for _ in range(5):
                  pool.submit(add_money, account)
                  pool.submit(sub_money, account)
      
      
      if __name__ == '__main__':
          main()
      
    • 多进程:多进程可以有效的解决GIL的问题,实现多进程主要的类是Process,其他辅助的类跟threading模块中的类似,进程间共享数据可以使用管道、套接字等,在multiprocessing模块中有一个Queue类,它基于管道和锁机制提供了多个进程共享的队列。下面是官方文档上关于多进程和进程池的一个示例。

      """
      多进程和进程池的使用
      多线程因为GIL的存在不能够发挥CPU的多核特性
      对于计算密集型任务应该考虑使用多进程
      time python3 example22.py
      real    0m11.512s
      user    0m39.319s
      sys     0m0.169s
      使用多进程后实际执行时间为11.512秒,而用户时间39.319秒约为实际执行时间的4倍
      这就证明我们的程序通过多进程使用了CPU的多核特性,而且这台计算机配置了4核的CPU
      """
      import concurrent.futures
      import math
      
      PRIMES = [
          1116281,
          1297337,
          104395303,
          472882027,
          533000389,
          817504243,
          982451653,
          112272535095293,
          112582705942171,
          112272535095293,
          115280095190773,
          115797848077099,
          1099726899285419
      ] * 5
      
      
      def is_prime(n):
          """判断素数"""
          if n % 2 == 0:
              return False
      
          sqrt_n = int(math.floor(math.sqrt(n)))
          for i in range(3, sqrt_n + 1, 2):
              if n % i == 0:
                  return False
          return True
      
      
      def main():
          """主函数"""
          with concurrent.futures.ProcessPoolExecutor() as executor:
              for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
                  print('%d is prime: %s' % (number, prime))
      
      
      if __name__ == '__main__':
          main()
      

      说明:多线程和多进程的比较

      以下情况需要使用多线程:

      1. 程序需要维护许多共享的状态(尤其是可变状态),Python中的列表、字典、集合都是线程安全的,所以使用线程而不是进程维护共享状态的代价相对较小。
      2. 程序会花费大量时间在I/O操作上,没有太多并行计算的需求且不需占用太多的内存。

      以下情况需要使用多进程:

      1. 程序执行计算密集型任务(如:字节码操作、数据处理、科学计算)。
      2. 程序的输入可以并行的分成块,并且可以将运算结果合并。
      3. 程序在内存使用方面没有任何限制且不强依赖于I/O操作(如:读写文件、套接字等)。
    • 异步处理:从调度程序的任务队列中挑选任务,该调度程序以交叉的形式执行这些任务,我们并不能保证任务将以某种顺序去执行,因为执行顺序取决于队列中的一项任务是否愿意将CPU处理时间让位给另一项任务。异步任务通常通过多任务协作处理的方式来实现,由于执行时间和顺序的不确定,因此需要通过回调式编程或者future对象来获取任务执行的结果。Python 3通过asyncio模块和awaitasync关键字(在Python 3.7中正式被列为关键字)来支持异步处理。

      """
      异步I/O - async / await
      """
      import asyncio
      
      
      def num_generator(m, n):
          """指定范围的数字生成器"""
          yield from range(m, n + 1)
      
      
      async def prime_filter(m, n):
          """素数过滤器"""
          primes = []
          for i in num_generator(m, n):
              flag = True
              for j in range(2, int(i ** 0.5 + 1)):
                  if i % j == 0:
                      flag = False
                      break
              if flag:
                  print('Prime =>', i)
                  primes.append(i)
      
              await asyncio.sleep(0.001)
          return tuple(primes)
      
      
      async def square_mapper(m, n):
          """平方映射器"""
          squares = []
          for i in num_generator(m, n):
              print('Square =>', i * i)
              squares.append(i * i)
      
              await asyncio.sleep(0.001)
          return squares
      
      
      def main():
          """主函数"""
          loop = asyncio.get_event_loop()
          future = asyncio.gather(prime_filter(2, 100), square_mapper(1, 100))
          future.add_done_callback(lambda x: print(x.result()))
          loop.run_until_complete(future)
          loop.close()
      
      
      if __name__ == '__main__':
          main()
      

      说明:上面的代码使用get_event_loop函数获得系统默认的事件循环,通过gather函数可以获得一个future对象,future对象的add_done_callback可以添加执行完成时的回调函数,loop对象的run_until_complete方法可以等待通过future对象获得协程执行结果。

      Python中有一个名为aiohttp的三方库,它提供了异步的HTTP客户端和服务器,这个三方库可以跟asyncio模块一起工作,并提供了对Future对象的支持。Python 3.6中引入了async和await来定义异步执行的函数以及创建异步上下文,在Python 3.7中它们正式成为了关键字。下面的代码异步的从5个URL中获取页面并通过正则表达式的命名捕获组提取了网站的标题。

      import asyncio
      import re
      
      import aiohttp
      
      PATTERN = re.compile(r'\(?P.*)\<\/title\>')
      
      
      async def fetch_page(session, url):
          async with session.get(url, ssl=False) as resp:
              return await resp.text()
      
      
      async def show_title(url):
          async with aiohttp.ClientSession() as session:
              html = await fetch_page(session, url)
              print(PATTERN.search(html).group('title'))
      
      
      def main():
          urls = ('https://www.python.org/',
                  'https://git-scm.com/',
                  'https://www.jd.com/',
                  'https://www.taobao.com/',
                  'https://www.douban.com/')
          loop = asyncio.get_event_loop()
          tasks = [show_title(url) for url in urls]
          loop.run_until_complete(asyncio.wait(tasks))
          loop.close()
      
      
      if __name__ == '__main__':
          main()
      </code></pre> 
           <blockquote> 
            <p>说明:<strong>异步I/O与多进程的比较</strong>。</p> 
            <p>当程序不需要真正的并发性或并行性,而是更多的依赖于异步处理和回调时,asyncio就是一种很好的选择。如果程序中有大量的等待与休眠时,也应该考虑asyncio,它很适合编写没有实时数据处理需求的Web应用服务器。</p> 
           </blockquote> <p>Python还有很多用于处理并行任务的三方库,例如:joblib、PyMP等。实际开发中,要提升系统的可扩展性和并发性通常有垂直扩展(增加单个节点的处理能力)和水平扩展(将单个节点变成多个节点)两种做法。可以通过消息队列来实现应用程序的解耦合,消息队列相当于是多线程同步队列的扩展版本,不同机器上的应用程序相当于就是线程,而共享的分布式消息队列就是原来程序中的Queue。消息队列(面向消息的中间件)的最流行和最标准化的实现是AMQP(高级消息队列协议),AMQP源于金融行业,提供了排队、路由、可靠传输、安全等功能,最著名的实现包括:Apache的ActiveMQ、RabbitMQ等。</p> <p>Celery是Python编写的分布式任务队列,它使用分布式消息进行工作,可以基于RabbitMQ或Redis来作为后端的消息代理,这个内容我们会在项目中讲到。</p> </li> 
         </ul> </li> 
       </ol> 
       <h3>第04天:团队开发和项目选题</h3> 
       <ol> 
        <li> <p>软件过程模型</p> 
         <ul> 
          <li> <p>经典过程模型(瀑布模型)</p> 
           <ul> 
            <li>可行性分析(研究做还是不做),输出《可行性分析报告》。</li> 
            <li>需求分析(研究做什么),输出《需求规格说明书》和产品界面原型图。</li> 
            <li>概要设计和详细设计,输出概念模型图、物理模型图、类图、时序图等。</li> 
            <li>编码 / 测试。</li> 
            <li>上线 / 维护。</li> 
           </ul> </li> 
          <li> <p>敏捷开发(Scrum)</p> 
           <ul> 
            <li>产品的Backlog(用户故事、产品原型)。</li> 
            <li>计划会议(评估、预算、进度)。</li> 
            <li>日常开发(站立会议、番茄工作法、结对编程、测试先行、代码重构……)。</li> 
            <li>修复bug(问题描述、重现步骤、测试人员、被指派人)。</li> 
            <li>评审会议(Showcase)。</li> 
            <li>回顾会议(当前周期做得好和不好的地方)。</li> 
           </ul> 
           <blockquote> 
            <p>补充:敏捷软件开发宣言</p> 
            <ul> 
             <li> <strong>个体和互动</strong> 高于 流程和工具</li> 
             <li> <strong>工作的软件</strong> 高于 详尽的文档</li> 
             <li> <strong>客户合作</strong> 高于 合同谈判</li> 
             <li> <strong>响应变化</strong> 高于 遵循计划</li> 
            </ul> 
           </blockquote> </li> 
         </ul> <p>[图片上传失败...(image-af7c78-1558321309426)]</p> 
         <blockquote> 
          <p>角色:产品所有者(决定做什么,能对需求拍板的人)、团队负责人(解决各种问题,专注如何更好的工作,屏蔽外部对开发团队的影响)、开发团队(项目执行人员,具体指开发人员和测试人员)</p> 
          <p>准备工作:商业案例和资金、合同、憧憬、初始产品需求、初始发布计划、入股、组建团队</p> 
          <p>敏捷团队通常人数为8-10人。</p> 
          <p>工作量估算:将开发任务量化,包括原型、Logo设计、UI设计、前端开发等,尽量把每个工作分解到最小任务量,最小任务量标准为工作时间不能超过两天,然后估算总体项目时间。把每个任务都贴在白板上面,白板上分三部分:to do(待完成)、in progress(进行中)和done(已完成)。</p> 
         </blockquote> </li> 
        <li> <p>项目团队组建</p> 
         <ul> 
          <li> <p>团队的构成和角色</p> <p>[图片上传失败...(image-65edd-1558321309426)]</p> </li> 
          <li> <p>编程规范和代码审查(flake8、pylint)</p> <p>[图片上传失败...(image-2c20d-1558321309426)]</p> </li> 
          <li><p>Python中的一些“惯例”(请参考《Python惯例-如何编写Pythonic的代码》)</p></li> 
          <li> <p>影响代码可读性的原因:</p> 
           <ul> 
            <li>代码注释太少或者没有注释</li> 
            <li>代码破坏了语言的最佳实践</li> 
            <li>反模式编程(意大利面代码、复制-黏贴编程、自负编程、……)</li> 
           </ul> </li> 
         </ul> </li> 
        <li> <p>团队开发工具介绍</p> 
         <ul> 
          <li>版本控制:Git、Mercury</li> 
          <li>缺陷管理:Gitlab、Redmine </li> 
          <li>敏捷闭环工具:禅道、JIRA </li> 
          <li>持续集成:Jenkins、Travis-CI </li> 
         </ul> <p>请参考《团队项目开发》。</p> </li> 
       </ol> 
       <h4>项目选题和理解业务</h4> 
       <ol> 
        <li> <p>选题范围设定</p> 
         <ul> 
          <li><p>CMS(用户端):新闻聚合网站、问答/分享社区、影评/书评网站等。</p></li> 
          <li><p>MIS(用户端+管理端):KMS、KPI考核系统、HRS、CRM系统、供应链系统、仓储管理系统等。</p></li> 
          <li><p>App后台(管理端+数据接口):二手交易类、报刊杂志类、小众电商类、新闻资讯类、旅游类、社交类、阅读类等。</p></li> 
          <li><p>其他类型:自身行业背景和工作经验、业务容易理解和把控。</p></li> 
         </ul> </li> 
        <li> <p>需求理解、模块划分和任务分配</p> 
         <ul> 
          <li>需求理解:头脑风暴和竞品分析。</li> 
          <li>模块划分:画思维导图(XMind),每个模块是一个枝节点,每个具体的功能是一个叶节点(用动词表述),需要确保每个叶节点无法再生出新节点,确定每个叶子节点的重要性、优先级和工作量。</li> 
          <li>任务分配:由项目负责人根据上面的指标为每个团队成员分配任务。</li> 
         </ul> <p>[图片上传失败...(image-c02b5b-1558321309426)]</p> </li> 
        <li> <p>制定项目进度表(每日更新)</p> 
         <table> 
          <thead> 
           <tr> 
            <th>模块</th> 
            <th>功能</th> 
            <th>人员</th> 
            <th>状态</th> 
            <th>完成</th> 
            <th>工时</th> 
            <th>计划开始</th> 
            <th>实际开始</th> 
            <th>计划结束</th> 
            <th>实际结束</th> 
            <th>备注</th> 
           </tr> 
          </thead> 
          <tbody> 
           <tr> 
            <td>评论</td> 
            <td>添加评论</td> 
            <td>王大锤</td> 
            <td>正在进行</td> 
            <td>50%</td> 
            <td>4</td> 
            <td>2018/8/7</td> 
            <td></td> 
            <td>2018/8/7</td> 
            <td></td> 
            <td></td> 
           </tr> 
           <tr> 
            <td></td> 
            <td>删除评论</td> 
            <td>王大锤</td> 
            <td>等待</td> 
            <td>0%</td> 
            <td>2</td> 
            <td>2018/8/7</td> 
            <td></td> 
            <td>2018/8/7</td> 
            <td></td> 
            <td></td> 
           </tr> 
           <tr> 
            <td></td> 
            <td>查看评论</td> 
            <td>白元芳</td> 
            <td>正在进行</td> 
            <td>20%</td> 
            <td>4</td> 
            <td>2018/8/7</td> 
            <td></td> 
            <td>2018/8/7</td> 
            <td></td> 
            <td>需要进行代码审查</td> 
           </tr> 
           <tr> 
            <td></td> 
            <td>评论投票</td> 
            <td>白元芳</td> 
            <td>等待</td> 
            <td>0%</td> 
            <td>4</td> 
            <td>2018/8/8</td> 
            <td></td> 
            <td>2018/8/8</td> 
            <td></td> 
            <td></td> 
           </tr> 
          </tbody> 
         </table> </li> 
       </ol> 
       <h3>第05天:数据库设计和OOAD</h3> 
       <h4>概念模型和正向工程</h4> 
       <ol> 
        <li> <p>UML(统一建模语言)的类图</p> <p>[图片上传失败...(image-5a8dcf-1558321309426)]</p> </li> 
        <li> <p>通过模型创建表(正向工程)</p> <pre><code class="Shell">python manage.py makemigrations app
      python manage.py migrate
      </code></pre> </li> 
       </ol> 
       <h4>物理模型和反向工程</h4> 
       <ol> 
        <li> <p>PowerDesigner</p> <p>[图片上传失败...(image-bab72e-1558321309426)]</p> </li> 
        <li> <p>通过数据表创建模型(反向工程)</p> <pre><code class="Shell">python manage.py inspectdb > app/models.py
      </code></pre> </li> 
       </ol> 
       <h3>第06-10天:使用Django开发项目</h3> 
       <blockquote> 
        <p>说明:具体内容请参考《Django知识点概述》</p> 
       </blockquote> 
       <h4>项目开发中的公共问题</h4> 
       <ol> 
        <li>数据库的配置(多数据库、主从复制、数据库路由)</li> 
        <li>缓存的配置(分区缓存、键设置、超时设置、主从复制、故障恢复(哨兵))</li> 
        <li>日志的配置</li> 
        <li>分析和调试(Django-Debug-ToolBar)</li> 
        <li>好用的Python模块(日期计算、图像处理、数据加密、三方API)</li> 
       </ol> 
       <h4>REST API设计</h4> 
       <ol> 
        <li>RESTful架构 
         <ul> 
          <li>理解RESTful架构</li> 
          <li>RESTful API设计指南</li> 
          <li>RESTful API最佳实践</li> 
         </ul> </li> 
        <li>API接口文档的撰写(《网络API接口设计》) 
         <ul> 
          <li>RAP2</li> 
          <li>YAPI</li> 
         </ul> </li> 
        <li> django-REST-framework的应用</li> 
       </ol> 
       <h4>项目中的重点难点剖析</h4> 
       <ol> 
        <li>使用缓存缓解数据库压力 - Redis</li> 
        <li>使用消息队列做解耦合和削峰 - Celery + RabbitMQ</li> 
       </ol> 
       <h3>第11-12天:测试和部署</h3> 
       <h4>单元测试</h4> 
       <ol> 
        <li>测试的种类</li> 
        <li>编写单元测试(unittest、pytest、nose2、tox、ddt、……)</li> 
        <li>测试覆盖率(coverage)</li> 
       </ol> 
       <h4>项目部署</h4> 
       <blockquote> 
        <p>说明:请参考《项目部署上线指南》。</p> 
       </blockquote> 
       <ol> 
        <li>部署前的准备工作 
         <ul> 
          <li>关键设置(SECRET_KEY / DEBUG / ALLOWED_HOSTS / 缓存 / 数据库)</li> 
          <li>HTTPS / CSRF_COOKIE_SECUR / SESSION_COOKIE_SECURE</li> 
          <li>日志相关配置</li> 
         </ul> </li> 
        <li>Linux常用命令回顾</li> 
        <li>Linux常用服务的安装和配置</li> 
        <li>uWSGI/Gunicorn和Nginx的使用 
         <ul> 
          <li>Gunicorn和uWSGI的比较 
           <ul> 
            <li>对于不需要大量定制化的简单应用程序,Gunicorn是一个不错的选择,uWSGI的学习曲线比Gunicorn要陡峭得多,Gunicorn的默认参数就已经能够适应大多数应用程序。</li> 
            <li>uWSGI支持异构部署。</li> 
            <li>由于Nginx本身支持uWSGI,在线上一般都将Nginx和uWSGI捆绑在一起部署,而且uWSGI属于功能齐全且高度定制的WSGI中间件。</li> 
            <li>在性能上,Gunicorn和uWSGI其实表现相当。</li> 
           </ul> </li> 
         </ul> </li> 
        <li>虚拟化技术(Docker)</li> 
       </ol> 
       <h4>性能测试</h4> 
       <blockquote> 
        <p>说明:具体内容请参考《Django知识点概述》。</p> 
       </blockquote> 
       <ol> 
        <li>AB的使用</li> 
        <li>SQLslap的使用</li> 
        <li>sysbench的使用</li> 
       </ol> 
       <h4>自动化测试</h4> 
       <ol> 
        <li>使用Shell和Python进行自动化测试</li> 
        <li>使用Selenium实现自动化测试 
         <ul> 
          <li>Selenium IDE</li> 
          <li>Selenium WebDriver</li> 
          <li>Selenium Remote Control</li> 
         </ul> </li> 
        <li>测试工具Robot Framework介绍</li> 
       </ol> 
       <h4>项目性能调优</h4> 
       <ol> 
        <li>数据库服务器性能调优 - 请参考《MySQL相关知识》 
         <ul> 
          <li>软硬件优化</li> 
          <li>SQL优化</li> 
          <li>架构优化 
           <ul> 
            <li>分库分表</li> 
            <li>主从复制,读写分离</li> 
            <li>集群架构</li> 
           </ul> </li> 
         </ul> </li> 
        <li>Web服务器性能优化 
         <ul> 
          <li>Nginx负载均衡配置</li> 
          <li>Keepalived实现高可用</li> 
         </ul> </li> 
        <li>代码性能调优 
         <ul> 
          <li>多线程</li> 
          <li>异步化</li> 
         </ul> </li> 
        <li>静态资源访问优化 
         <ul> 
          <li>云存储</li> 
          <li>CDN</li> 
         </ul> </li> 
       </ol> 
       <h3>结束:项目答辩和简历指导</h3> 
       <ol> 
        <li>Showcase</li> 
        <li>简历指导</li> 
        <li>面试话术</li> 
       </ol> 
      </article>
                                  </div>
                              </div>
                          </div>
                          <!--PC和WAP自适应版-->
                          <div id="SOHUCS" sid="1690077523578269696"></div>
                          <script type="text/javascript" src="/views/front/js/chanyan.js"></script>
                          <!-- 文章页-底部 动态广告位 -->
                          <div class="youdao-fixed-ad" id="detail_ad_bottom"></div>
                      </div>
                      <div class="col-md-3">
                          <div class="row" id="ad">
                              <!-- 文章页-右侧1 动态广告位 -->
                              <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                                  <div class="youdao-fixed-ad" id="detail_ad_1"> </div>
                              </div>
                              <!-- 文章页-右侧2 动态广告位 -->
                              <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                                  <div class="youdao-fixed-ad" id="detail_ad_2"></div>
                              </div>
                              <!-- 文章页-右侧3 动态广告位 -->
                              <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                                  <div class="youdao-fixed-ad" id="detail_ad_3"></div>
                              </div>
                          </div>
                      </div>
                  </div>
              </div>
          </div>
          <div class="container">
              <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(数据结构 各种查找算法)</h4>
              <div id="paradigm-article-related">
                  <div class="recommend-post mb30">
                      <ul class="widget-links">
                          <li><a href="/article/1886366270299893760.htm"
                                 title="潜水员 ← 二维费用的背包问题" target="_blank">潜水员 ← 二维费用的背包问题</a>
                              <span class="text-muted">hnjzsyjyj</span>
      <a class="tag" taget="_blank" href="/search/%E4%BF%A1%E6%81%AF%E5%AD%A6%E7%AB%9E%E8%B5%9B/1.htm">信息学竞赛</a><a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/1.htm">动态规划</a><a class="tag" taget="_blank" href="/search/%E4%BA%8C%E7%BB%B4%E8%B4%B9%E7%94%A8%E7%9A%84%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98/1.htm">二维费用的背包问题</a>
                              <div>【题目来源】https://www.acwing.com/problem/content/1022/【题目描述】潜水员为了潜水要使用特殊的装备。他有一个带2种气体的气缸:一个为氧气,一个为氮气。让潜水员下潜的深度需要各种数量的氧和氮。潜水员有一定数量的气缸。每个气缸都有重量和气体容量。潜水员为了完成他的工作需要特定数量的氧和氮。他完成工作所需气缸的总重的最低限度的是多少?例如:潜水员有5个气缸。每</div>
                          </li>
                          <li><a href="/article/1886365260693172224.htm"
                                 title="【数据结构与算法】力扣 5. 最长回文子串" target="_blank">【数据结构与算法】力扣 5. 最长回文子串</a>
                              <span class="text-muted">秀秀_heo</span>
      <a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/1.htm">数据结构与算法</a><a class="tag" taget="_blank" href="/search/leetcode/1.htm">leetcode</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E8%81%8C%E5%9C%BA%E5%92%8C%E5%8F%91%E5%B1%95/1.htm">职场和发展</a>
                              <div>题目描述5.最长回文子串给你一个字符串s,找到s中最长的回文子串。示例1:输入:s="babad"输出:"bab"解释:"aba"同样是符合题意的答案。示例2:输入:s="cbbd"输出:"bb"提示:1=0&&rightmaxLen){start=oddStart;maxLen=oddLen;}//处理偶数长度回文let[evenStart,evenLen]=expandAroundCenter</div>
                          </li>
                          <li><a href="/article/1886364756290367488.htm"
                                 title="Docker 安装详细教程(适用于CentOS 7 系统)" target="_blank">Docker 安装详细教程(适用于CentOS 7 系统)</a>
                              <span class="text-muted">Future_yzx</span>
      <a class="tag" taget="_blank" href="/search/eureka/1.htm">eureka</a><a class="tag" taget="_blank" href="/search/%E4%BA%91%E5%8E%9F%E7%94%9F/1.htm">云原生</a>
                              <div>目录步骤如下:1.卸载旧版Docker2.配置Docker的YUM仓库3.安装Docker4.启动Docker并验证安装5.配置Docker镜像加速总结前言Docker分为CE和EE两大版本。CE即社区版(免费,支持周期7个月);EE即企业版,强调安全,付费使用,支持周期24个月。DockerCE分为stabletest和nightly三个更新频道。官方网站上有各种环境下的安装指南,这里主要介绍D</div>
                          </li>
                          <li><a href="/article/1886356178313736192.htm"
                                 title="告别破解版!EDU邮箱可畅享Adobe全家桶,还有这5个冷门技巧等你解锁" target="_blank">告别破解版!EDU邮箱可畅享Adobe全家桶,还有这5个冷门技巧等你解锁</a>
                              <span class="text-muted">shelby_loo</span>
      <a class="tag" taget="_blank" href="/search/adobe/1.htm">adobe</a>
                              <div>还在为破解版Adobe软件的各种问题头疼吗?是时候和它们说再见了!现在,通过EDU教育邮箱,你就可以免费使用正版Adobe系列软件,告别破解版带来的烦恼。如何获取EDU邮箱?想要了解如何获取EDU邮箱,你可以参考我昨天的文章。掌握这5个冷门技巧,让你的Adobe软件技能更上一层楼Photoshop:快速抠图不求人还在用魔棒工具或者钢笔工具辛苦抠图?试试Photoshop的“选择并遮罩”功能吧!它能</div>
                          </li>
                          <li><a href="/article/1886350753258336256.htm"
                                 title="【App渗透】用BurpSuite抓包安卓手机app内容(详细)_burpsuite抓app" target="_blank">【App渗透】用BurpSuite抓包安卓手机app内容(详细)_burpsuite抓app</a>
                              <span class="text-muted">2401_84520271</span>
      <a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98/1.htm">程序员</a><a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/%E6%99%BA%E8%83%BD%E6%89%8B%E6%9C%BA/1.htm">智能手机</a>
                              <div>四、抓包总结前言很多情况下,在电脑的手机模拟器上面做app测试会存在大大小小的bug或者各种坑,而且有些模拟器很不方便,非常不好用。网上的教程虽然多,但是大部分都是两年前的甚至更晚的,跟着一步步来也是会错。为了避免这种情况的发生,所以有了这篇文章。在本机上面做app渗透,才是最稳定的。当然,我检测的app都是公司的产品,如果是你们要测一个不知情的app,还是建议杀杀毒,或者另外某上面买一台二手的安</div>
                          </li>
                          <li><a href="/article/1886343689056350208.htm"
                                 title="如何在Java中调用Python" target="_blank">如何在Java中调用Python</a>
                              <span class="text-muted">梦想画家</span>
      <a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/java8%7E9%E6%A0%B8%E5%BF%83%E5%8A%9F%E8%83%BD/1.htm">java8~9核心功能</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/jython/1.htm">jython</a>
                              <div>Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用。DataX是阿里开源的一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。Datax也是通过Java调用Python脚本。本文介绍几种方法从java调用Py</div>
                          </li>
                          <li><a href="/article/1886342931497938944.htm"
                                 title="读书笔记-《Redis设计与实现》(二)单机数据库实现(上)" target="_blank">读书笔记-《Redis设计与实现》(二)单机数据库实现(上)</a>
                              <span class="text-muted">萝卜青今天也要开心</span>
      <a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/%E7%BC%93%E5%AD%98/1.htm">缓存</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a>
                              <div>相比前面我们学习的数据结构与对象(读书笔记-《Redis设计与实现》(一)数据结构与对象(上)、读书笔记-《Redis设计与实现》(一)数据结构与对象(下)),这部分的内容可以说就是轻松+愉快了,只要能Get到这几个机制的要点就行。01数据库Redis将所有数据库都保存在redisServer结构中,客户端结构为redisClient,它们的关键属性如下:structredisServer{//一</div>
                          </li>
                          <li><a href="/article/1886340790469324800.htm"
                                 title="Python基本数据类型之字符串" target="_blank">Python基本数据类型之字符串</a>
                              <span class="text-muted">stiinput</span>
      <a class="tag" taget="_blank" href="/search/Python%E7%9F%A5%E8%AF%86%E9%9B%86/1.htm">Python知识集</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                              <div>文章目录变量类型之字符串一、字符串的性质二、字符串的分类1.字符串又分为转义字符、原始字符串和一般字符串三种。三、字符串的基本操作1.字符串能实现拼接、重复、成员运算、比较大小等基本操作,其中比较大小还涉及到进制转换。2.字符串也能实现跟列表一样的通过下标找元素,切片等操作。3.字符串的遍历也有两种四、字符串的方法1.字符串的方法有:2.字符串的各种方法的应用3.字符串方法的补充五、字符串推导式变</div>
                          </li>
                          <li><a href="/article/1886334225465012224.htm"
                                 title="Ultralight - Digital - Human:移动端实时运行的超轻量级数字人模型" target="_blank">Ultralight - Digital - Human:移动端实时运行的超轻量级数字人模型</a>
                              <span class="text-muted">花生糖@</span>
      <a class="tag" taget="_blank" href="/search/AIGC%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99%E5%BA%93/1.htm">AIGC学习资料库</a><a class="tag" taget="_blank" href="/search/AI/1.htm">AI</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E5%AD%97%E4%BA%BA/1.htm">数字人</a><a class="tag" taget="_blank" href="/search/%E8%BD%BB%E9%87%8F%E7%BA%A7%E6%A8%A1%E5%9E%8B/1.htm">轻量级模型</a>
                              <div>在数字人技术日益发展的今天,我们迎来了一个令人瞩目的项目——Ultralight-Digital-Human。这是一个由anliyuan等人开发的创新项目,为数字人技术在移动端的应用带来了新的可能性。一、项目概述Ultralight-Digital-Human旨在构建一个超轻量级的数字人模型,并且能够在移动端实现实时运行。这一特性使得它在众多数字人项目中脱颖而出,为移动设备上的各种应用场景提供了更</div>
                          </li>
                          <li><a href="/article/1886316329774936064.htm"
                                 title="Highcharts 条形图:数据可视化的利器" target="_blank">Highcharts 条形图:数据可视化的利器</a>
                              <span class="text-muted">lly202406</span>
      <a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                              <div>Highcharts条形图:数据可视化的利器引言在数据分析和可视化领域,Highcharts是一个广受欢迎的JavaScript图表库。它以其易用性、灵活性和丰富的图表类型而著称。其中,条形图作为一种基础但功能强大的图表类型,被广泛应用于各种场景,以直观地展示数据分布和比较。本文将深入探讨Highcharts中的条形图,包括其基本用法、高级配置以及在实际应用中的最佳实践。什么是Highcharts</div>
                          </li>
                          <li><a href="/article/1886312670622183424.htm"
                                 title="Java 集合框架:HashMap 的介绍、使用、原理与源码解析" target="_blank">Java 集合框架:HashMap 的介绍、使用、原理与源码解析</a>
                              <span class="text-muted">NicoleGus</span>
      <a class="tag" taget="_blank" href="/search/%E5%93%88%E5%B8%8C%E7%AE%97%E6%B3%95/1.htm">哈希算法</a><a class="tag" taget="_blank" href="/search/%E6%95%A3%E5%88%97%E8%A1%A8/1.htm">散列表</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a>
                              <div>一、HashMap介绍HashMap是Java集合框架中最常用的数据结构之一。它实现了Map接口,允许我们以键值对的形式存储数据。HashMap的主要特点是通过哈希表(HashTable)来实现对数据的高效查找、插入和删除操作。1.特性无序存储:HashMap并不保证元素的顺序,元素的顺序可能会随着插入的顺序和哈希冲突的解决方式而变化。允许null键和null值:HashMap允许一个null键和</div>
                          </li>
                          <li><a href="/article/1886311028808019968.htm"
                                 title="mac安装python" target="_blank">mac安装python</a>
                              <span class="text-muted">一口八宝周</span>
      <a class="tag" taget="_blank" href="/search/macos/1.htm">macos</a>
                              <div>接上集,我们已经安装了Homebrew那么在macOS上安装Python有多种方法,以下是其中两种常用方法:1:使用Homebrew安装PythonHomebrew是macOS上的包管理器,可以方便地安装和管理各种软件包。如果您已经安装了Homebrew,可以使用以下命令安装Python:打开终端(Terminal)应用程序。运行以下命令安装Homebrew/bin/bash-c"$(curl-f</div>
                          </li>
                          <li><a href="/article/1886308760050266112.htm"
                                 title="Oracle 分区在什么情况下使用?思维导图 代码示例(java 架构)" target="_blank">Oracle 分区在什么情况下使用?思维导图 代码示例(java 架构)</a>
                              <span class="text-muted">用心去追梦</span>
      <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a>
                              <div>Oracle分区的适用场景Oracle分区(Partitioning)是一种强大的数据管理工具,适用于特定类型的数据库工作负载和数据结构。以下是一些适合使用分区的情况:1.大型表优化超大数据量:当表包含数百万甚至数十亿行时,分区可以帮助提高查询性能。频繁更新:对于经常被插入、更新或删除的数据,分区可以减少锁定范围,提高并发性。2.数据仓库历史数据分析:在数据仓库中,通常会存储多年的历史数据。通过按</div>
                          </li>
                          <li><a href="/article/1886308505875443712.htm"
                                 title="Highcharts 柱形图:深入解析与最佳实践" target="_blank">Highcharts 柱形图:深入解析与最佳实践</a>
                              <span class="text-muted">lsx202406</span>
      <a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                              <div>Highcharts柱形图:深入解析与最佳实践引言Highcharts是一个功能强大的图表库,它允许用户轻松地在网页上创建各种类型的图表。其中,柱形图因其直观的展示方式,在数据分析、业务报告等领域得到了广泛应用。本文将深入解析Highcharts柱形图,包括其基本用法、高级特性以及最佳实践。高charts柱形图的基本用法1.初始化图表首先,需要在HTML文件中引入Highcharts库。以下是一个</div>
                          </li>
                          <li><a href="/article/1886298289217794048.htm"
                                 title="线性回归基础学习" target="_blank">线性回归基础学习</a>
                              <span class="text-muted">Remoa</span>
      <a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%BD%92/1.htm">线性回归</a><a class="tag" taget="_blank" href="/search/%E4%BC%98%E5%8C%96/1.htm">优化</a><a class="tag" taget="_blank" href="/search/gluon/1.htm">gluon</a><a class="tag" taget="_blank" href="/search/mxnet/1.htm">mxnet</a><a class="tag" taget="_blank" href="/search/loss/1.htm">loss</a>
                              <div>线性回归基础学习目录:理论知识样例代码测试参考文献一、理论知识线性回归思维导图NDArray:MXNet中存储和变换数据的主要工具,提供GPU计算和自动求梯度等功能线性回归可以用神经网络图表示,也可以用矢量计算表示在Gluon中,data模块提供了有关数据处理的工具,nn模块定义了大量神经网络的层,loss模块定义了各种损失函数在MXNet的init模块(initializer)提供了模型参数化的</div>
                          </li>
                          <li><a href="/article/1886289718623137792.htm"
                                 title="软件设计师概念之 耦合类型" target="_blank">软件设计师概念之 耦合类型</a>
                              <span class="text-muted">一坨仙女</span>
      <a class="tag" taget="_blank" href="/search/%E8%BD%AF%E8%80%83/1.htm">软考</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a>
                              <div>耦合类型:(1)内容耦合:如果发生下列情形,两个模块之间就发生了内容耦合1.一个模块直接访问另一个模块的内部数据;2.一个模块不通过正常入口转到另一模块内部;3.两个模块有一部分程序代码重迭**(只可能出现在汇编语言中)**;4.一个模块有多个入口。(2)公共耦合:若一组模块都访问同一个公共数据环境,则它们之间的耦合就称为公共耦合。公共的数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等</div>
                          </li>
                          <li><a href="/article/1886276351808303104.htm"
                                 title="基于CNN(一维卷积Conv1D)+LSTM+Attention 实现股票多变量时间序列预测(PyTorch版)" target="_blank">基于CNN(一维卷积Conv1D)+LSTM+Attention 实现股票多变量时间序列预测(PyTorch版)</a>
                              <span class="text-muted">矩阵猫咪</span>
      <a class="tag" taget="_blank" href="/search/cnn/1.htm">cnn</a><a class="tag" taget="_blank" href="/search/lstm/1.htm">lstm</a><a class="tag" taget="_blank" href="/search/pytorch/1.htm">pytorch</a><a class="tag" taget="_blank" href="/search/%E6%B3%A8%E6%84%8F%E5%8A%9B%E6%9C%BA%E5%88%B6/1.htm">注意力机制</a><a class="tag" taget="_blank" href="/search/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1.htm">卷积神经网络</a><a class="tag" taget="_blank" href="/search/%E9%95%BF%E7%9F%AD%E6%9C%9F%E8%AE%B0%E5%BF%86%E7%BD%91%E7%BB%9C/1.htm">长短期记忆网络</a><a class="tag" taget="_blank" href="/search/Attention/1.htm">Attention</a>
                              <div>前言系列专栏:【深度学习:算法项目实战】✨︎涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域,讨论了各种复杂的深度神经网络思想,如卷积神经网络、循环神经网络、生成对抗网络、门控循环单元、长短期记忆、自然语言处理、深度强化学习、大型语言模型和迁移学习。在深度学习的众多模型中,卷积神经网络(CNN)和长短期记忆网络(LSTM)因其独特的优势</div>
                          </li>
                          <li><a href="/article/1886249229555396608.htm"
                                 title="深入剖析多叉树、红黑树与 B + 树:数据结构的异同与应用场景" target="_blank">深入剖析多叉树、红黑树与 B + 树:数据结构的异同与应用场景</a>
                              <span class="text-muted">109702008</span>
      <a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a>
                              <div>在计算机科学领域,数据结构是组织、存储和管理数据的重要工具,直接影响着算法的效率和系统的性能。多叉树、红黑树和B+树作为常用的数据结构,在不同的应用场景中发挥着关键作用。理解它们的特点、优势和适用场景,对于开发者设计高效的算法和系统至关重要。一、多叉树:灵活的层次结构表示多叉树是一种每个节点可以拥有多个子节点的树形数据结构,是树结构的一种广义形式。它的节点度数(子节点数量)没有严格限制,这种灵活性</div>
                          </li>
                          <li><a href="/article/1886247969087352832.htm"
                                 title="图神经网络实战(2)——图论基础" target="_blank">图神经网络实战(2)——图论基础</a>
                              <span class="text-muted">盼小辉丶</span>
      <a class="tag" taget="_blank" href="/search/%E5%9B%BE%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/1.htm">图神经网络从入门到项目实战</a><a class="tag" taget="_blank" href="/search/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1.htm">神经网络</a><a class="tag" taget="_blank" href="/search/%E5%9B%BE%E8%AE%BA/1.htm">图论</a><a class="tag" taget="_blank" href="/search/%E5%9B%BE%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1.htm">图神经网络</a><a class="tag" taget="_blank" href="/search/GNN/1.htm">GNN</a>
                              <div>图神经网络实战(2)——图论基础0.前言1.图属性1.1有向图和无向图1.2加权图和非加权图1.3连通图和非连通图1.4其它图类型2.图概念2.1基本对象2.2图的度量指标2.2邻接矩阵表示法3.图算法3.1广度优先搜索3.2深度优先搜索小结系列链接0.前言图论(Graphtheory)是数学的一个基本分支,涉及对图研究。图是复杂数据结构的可视化表示,有助于理解不同实体之间的关系。图论提供了大量建</div>
                          </li>
                          <li><a href="/article/1886226917443563520.htm"
                                 title="SSM火车订票管理系统 火车票务管理系统的设计与开发 基于SSM框架的火车票预订系统设计与实现" target="_blank">SSM火车订票管理系统 火车票务管理系统的设计与开发 基于SSM框架的火车票预订系统设计与实现</a>
                              <span class="text-muted">月影_计算机毕设</span>
      <a class="tag" taget="_blank" href="/search/%E8%AF%BE%E7%A8%8B%E8%AE%BE%E8%AE%A1/1.htm">课程设计</a>
                              <div>计算机毕业设计SSM火车订票管理系统3y92w(配套有源码程序mysql数据库论文)本套源码可以先看具体功能演示视频领取,文末有联xi可分享随着信息技术和网络技术的飞速发展,人类已进入全新的信息化时代,传统的管理技术已无法高效、便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代,火车订票管理系统就是信息时代变革中的产物之一。火车订票管理系统的开</div>
                          </li>
                          <li><a href="/article/1886225823195787264.htm"
                                 title="刷题前必学!时间复杂度和空间复杂度!用JavaScript学数据结构与算法" target="_blank">刷题前必学!时间复杂度和空间复杂度!用JavaScript学数据结构与算法</a>
                              <span class="text-muted"></span>
      
                              <div>‍JavaScript算法与数据结构-HowieCong务必要熟悉JavaScript使用再来学!一、时间复杂度(1)下面代码,一共执行了几次?functiontraverse(arr){//最没有悬念的是函数里面的第一行代码,只会被执行1次varlen=arr.length//1.i的初始化语句,只有一次,只会被执行1次//2.iO(n)=1T(n)=3n^2+5n+3=>O(n)=n^2(4)</div>
                          </li>
                          <li><a href="/article/1886223132834983936.htm"
                                 title="前端——vue代码结构" target="_blank">前端——vue代码结构</a>
                              <span class="text-muted">Alisazxy</span>
      <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                              <div>默认代码结构README.md---项目说明文件package.json---定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)。package-lock.json---会自动为npm修改node_modules树或任何操作而生成package.jsonLICENSE---开源协议index.html---项目默认首页模板.postcssrc.js---是对pos</div>
                          </li>
                          <li><a href="/article/1886220226513661952.htm"
                                 title="B站弹幕宠物练级脚本和B站猫猫养成练级脚本或者B站自动发弹幕(b站弹幕姬)" target="_blank">B站弹幕宠物练级脚本和B站猫猫养成练级脚本或者B站自动发弹幕(b站弹幕姬)</a>
                              <span class="text-muted">择~城</span>
      <a class="tag" taget="_blank" href="/search/pyinstaller/1.htm">pyinstaller</a><a class="tag" taget="_blank" href="/search/Python/1.htm">Python</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%BC%B9%E5%B9%95/1.htm">弹幕</a><a class="tag" taget="_blank" href="/search/%E8%84%9A%E6%9C%AC/1.htm">脚本</a><a class="tag" taget="_blank" href="/search/%E5%BC%B9%E5%B9%95%E5%AE%A0%E7%89%A9%E4%BF%AE%E7%82%BC/1.htm">弹幕宠物修炼</a><a class="tag" taget="_blank" href="/search/%E7%8C%AB%E7%8C%AB%E5%85%BB%E6%88%90/1.htm">猫猫养成</a>
                              <div>B站弹幕宠物练级脚本B站的弹幕宠物是一种创新的直播互动方式,(B站弹幕宠物练级脚本或者B站自动发弹幕(b站弹幕姬)实现途径都大差不差在直播间用脚本自动发弹幕就可以了),B站的弹幕宠物它允许观众通过发送弹幕指令来控制屏幕上的宠物进行各种动作,从而增加直播的趣味性和互动性。以下是对B站弹幕宠物的详细介绍:一、基本功能弹幕控制:观众可以通过发送特定的弹幕指令,如“左”、“右”、“前”、“后”加上数字表示</div>
                          </li>
                          <li><a href="/article/1886217073319800832.htm"
                                 title="使用支持向量机(SVM)进行股票市场预测" target="_blank">使用支持向量机(SVM)进行股票市场预测</a>
                              <span class="text-muted">m0_57781768</span>
      <a class="tag" taget="_blank" href="/search/%E6%94%AF%E6%8C%81%E5%90%91%E9%87%8F%E6%9C%BA/1.htm">支持向量机</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a>
                              <div>使用支持向量机(SVM)进行股票市场预测引言股票市场预测是金融领域的一个热门话题,也是一个充满挑战的研究领域。通过准确的市场预测,投资者可以做出更明智的决策,从而获得更高的回报。支持向量机(SVM)作为一种强大的机器学习算法,已被广泛应用于各种分类和回归问题。本文将详细介绍如何使用C++和支持向量机进行股票市场预测,并提供完整的代码示例。支持向量机简介支持向量机(SVM)是一种监督学习算法,最初用</div>
                          </li>
                          <li><a href="/article/1886212661251731456.htm"
                                 title="STMicroelectronics 系列:STM32L4 系列_(3).STM32L4系列的低功耗技术" target="_blank">STMicroelectronics 系列:STM32L4 系列_(3).STM32L4系列的低功耗技术</a>
                              <span class="text-muted">kkchenkx</span>
      <a class="tag" taget="_blank" href="/search/%E5%8D%95%E7%89%87%E6%9C%BA%E5%BC%80%E5%8F%91/1.htm">单片机开发</a><a class="tag" taget="_blank" href="/search/stm32/1.htm">stm32</a><a class="tag" taget="_blank" href="/search/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%A1%AC%E4%BB%B6/1.htm">嵌入式硬件</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E7%89%87%E6%9C%BA/1.htm">单片机</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a>
                              <div>STM32L4系列的低功耗技术1.低功耗概述STM32L4系列单片机是STMicroelectronics公司推出的高性能低功耗微控制器,广泛应用于各种需要长时间运行且功耗要求严格的嵌入式系统。低功耗技术是STM32L4系列的核心优势之一,通过多种机制和优化措施,实现了在不同工作模式下的最低功耗。2.低功耗工作模式STM32L4系列支持多种低功耗工作模式,包括低功耗运行模式(Low-PowerRu</div>
                          </li>
                          <li><a href="/article/1886210645091741696.htm"
                                 title="【Python】一文教你快速遍历文件夹下所有文件" target="_blank">【Python】一文教你快速遍历文件夹下所有文件</a>
                              <span class="text-muted">鸽芷咕</span>
      <a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                              <div>鸽芷咕:个人主页个人专栏:《C++干货基地》《粉丝福利》⛺️生活的理想,就是为了理想的生活!博主简介博主致力于嵌入式、Python、人工智能、C/C++领域和各种前沿技术的优质博客分享,用最优质的内容带来最舒适的阅读体验!在博客领域获得C/C++领域优质、CSDN年度征文第一、掘金2023年人气作者、华为云享专家、支付宝开放社区优质博主等头衔。个人社区&个人社群加入点击即可介绍加入链接个人社群社群</div>
                          </li>
                          <li><a href="/article/1886208121941061632.htm"
                                 title="数据结构基础1" target="_blank">数据结构基础1</a>
                              <span class="text-muted">四代目 水门</span>
      <a class="tag" taget="_blank" href="/search/%E5%B5%8C%E5%85%A5%E5%BC%8F%E9%9D%A2%E8%AF%95/1.htm">嵌入式面试</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/1.htm">排序算法</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a>
                              <div>什么是稳定排序和不稳定排序稳定排序和不稳定排序是排序算法的两种分类。稳定排序算法保证在排序过程中,相同元素的相对位置不变。不稳定排序算法则不保证在排序过程中,相同元素的相对位置不变。常见的稳定排序算法包括:冒泡排序快速排序常见的不稳定排序算法包括:选择排序堆排序二叉树前、中、后序遍历的规则前序遍历:先访问根结点、再前序遍历左子树、最后前序遍历右子树;中序遍历:中序遍历左子树、访问根节点、中序遍历右</div>
                          </li>
                          <li><a href="/article/1886192364389724160.htm"
                                 title="Windows 11 轻松设置:一键优化你的系统" target="_blank">Windows 11 轻松设置:一键优化你的系统</a>
                              <span class="text-muted">6v6博客</span>
      <a class="tag" taget="_blank" href="/search/css/1.htm">css</a>
                              <div>Windows11轻松设置是一款第三方软件,旨在帮助用户更轻松地配置和优化Windows11的各种设置。以下是它的主要功能和使用方法。功能亮点一键恢复默认设置:提供了一键恢复默认设置的功能,让用户可以随时撤销对系统设置的更改。自动关闭WindowsDefender实时保护:可以自动关闭WindowsDefender实时保护,让用户更容易安装一些被误报为病毒的应用程序。禁用WindowsUpdate</div>
                          </li>
                          <li><a href="/article/1886180634590769152.htm"
                                 title="从零开始构建一个简单的Python Web爬虫实战指南与技巧" target="_blank">从零开始构建一个简单的Python Web爬虫实战指南与技巧</a>
                              <span class="text-muted">一键难忘</span>
      <a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E7%88%AC%E8%99%AB/1.htm">爬虫</a><a class="tag" taget="_blank" href="/search/Python/1.htm">Python</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a>
                              <div>从零开始构建一个简单的PythonWeb爬虫实战指南与技巧随着数据科学和大数据分析的快速发展,网络爬虫(WebScraping)成为了获取互联网数据的重要工具。通过爬虫,我们可以自动化地从网页上获取各种信息,如新闻、产品价格、社交媒体内容等。本文将带您从零开始,使用Python构建一个简单的Web爬虫,抓取网页内容并保存数据。Web爬虫的基本概念什么是Web爬虫?Web爬虫(也称为网络蜘蛛或抓取器</div>
                          </li>
                          <li><a href="/article/1886170154820235264.htm"
                                 title="蓝桥备赛指南(5)" target="_blank">蓝桥备赛指南(5)</a>
                              <span class="text-muted">神里流~霜灭</span>
      <a class="tag" taget="_blank" href="/search/%E8%93%9D%E6%A1%A5%E5%A4%87%E8%B5%9B/1.htm">蓝桥备赛</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/%E8%B4%AA%E5%BF%83%E7%AE%97%E6%B3%95/1.htm">贪心算法</a><a class="tag" taget="_blank" href="/search/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/1.htm">动态规划</a><a class="tag" taget="_blank" href="/search/%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/1.htm">排序算法</a>
                              <div>queue队列queue是一种先进先出的数据结构。它提供了一组函数来操作和访问元素,但它的功能相对较简单,queue函数的内部实现了底层容器来存储元素,并且只能通过特定的函数来访问和操作元素。queue函数的常用函数1.push()函数:在队尾插入元素;2.pop()函数:弹出队首元素;3.front()函数:返回队首元素;4.back()函数:返回队尾元素;5.empty()函数:检查队列是否为</div>
                          </li>
                                      <li><a href="/article/87.htm"
                                             title="面向对象面向过程" target="_blank">面向对象面向过程</a>
                                          <span class="text-muted">3213213333332132</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                                          <div>面向对象:把要完成的一件事,通过对象间的协作实现。 
      面向过程:把要完成的一件事,通过循序依次调用各个模块实现。 
      我把大象装进冰箱这件事为例,用面向对象和面向过程实现,都是用java代码完成。 
       
      1、面向对象 
       
      
      package bigDemo.ObjectOriented;
      
      /**
       * 大象类
       * 
       * @Description
       * @author FuJian</div>
                                      </li>
                                      <li><a href="/article/214.htm"
                                             title="Java Hotspot: Remove the Permanent Generation" target="_blank">Java Hotspot: Remove the Permanent Generation</a>
                                          <span class="text-muted">bookjovi</span>
      <a class="tag" taget="_blank" href="/search/HotSpot/1.htm">HotSpot</a>
                                          <div>  
      openjdk上关于hotspot将移除永久带的描述非常详细,http://openjdk.java.net/jeps/122 
        
      JEP 122: Remove the Permanent Generation
      
      Author	Jon Masamitsu
      Organization	Oracle
      Created	2010/8/15
      Updated	2011/</div>
                                      </li>
                                      <li><a href="/article/341.htm"
                                             title="正则表达式向前查找向后查找,环绕或零宽断言" target="_blank">正则表达式向前查找向后查找,环绕或零宽断言</a>
                                          <span class="text-muted">dcj3sjt126com</span>
      <a class="tag" taget="_blank" href="/search/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/1.htm">正则表达式</a>
                                          <div>向前查找和向后查找 
      1. 向前查找:根据要匹配的字符序列后面存在一个特定的字符序列(肯定式向前查找)或不存在一个特定的序列(否定式向前查找)来决定是否匹配。.NET将向前查找称之为零宽度向前查找断言。 
          对于向前查找,出现在指定项之后的字符序列不会被正则表达式引擎返回。 
      2. 向后查找:一个要匹配的字符序列前面有或者没有指定的</div>
                                      </li>
                                      <li><a href="/article/468.htm"
                                             title="BaseDao" target="_blank">BaseDao</a>
                                          <span class="text-muted">171815164</span>
      <a class="tag" taget="_blank" href="/search/seda/1.htm">seda</a>
                                          <div>
      
      import java.sql.Connection;
      import java.sql.DriverManager;
      import java.sql.SQLException;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      
      public class BaseDao {
      
      	public Conn</div>
                                      </li>
                                      <li><a href="/article/595.htm"
                                             title="Ant标签详解--Java命令" target="_blank">Ant标签详解--Java命令</a>
                                          <span class="text-muted">g21121</span>
      <a class="tag" taget="_blank" href="/search/Java%E5%91%BD%E4%BB%A4/1.htm">Java命令</a>
                                          <div>        这一篇主要介绍与java相关标签的使用          终于开始重头戏了,Java部分是我们关注的重点也是项目中用处最多的部分。               
      1</div>
                                      </li>
                                      <li><a href="/article/722.htm"
                                             title="[简单]代码片段_电梯数字排列" target="_blank">[简单]代码片段_电梯数字排列</a>
                                          <span class="text-muted">53873039oycg</span>
      <a class="tag" taget="_blank" href="/search/%E4%BB%A3%E7%A0%81/1.htm">代码</a>
                                          <div>       今天看电梯数字排列是9 18 26这样呈倒N排列的,写了个类似的打印例子,如下:       
      import java.util.Arrays;
      
      public class 电梯数字排列_S3_Test {
      	public static void main(S</div>
                                      </li>
                                      <li><a href="/article/849.htm"
                                             title="Hessian原理" target="_blank">Hessian原理</a>
                                          <span class="text-muted">云端月影</span>
      <a class="tag" taget="_blank" href="/search/hessian%E5%8E%9F%E7%90%86/1.htm">hessian原理</a>
                                          <div>Hessian 原理分析 
       
       
       
       
       
      一.      远程通讯协议的基本原理 
       
      网络通信需要做的就是将流从一台计算机传输到另外一台计算机,基于传输协议和网络 IO 来实现,其中传输协议比较出名的有 http 、 tcp 、 udp 等等, http 、 tcp 、 udp 都是在基于 Socket 概念上为某类应用场景而扩展出的传输协</div>
                                      </li>
                                      <li><a href="/article/976.htm"
                                             title="区分Activity的四种加载模式----以及Intent的setFlags" target="_blank">区分Activity的四种加载模式----以及Intent的setFlags</a>
                                          <span class="text-muted">aijuans</span>
      <a class="tag" taget="_blank" href="/search/android/1.htm">android</a>
                                          <div>  
      在多Activity开发中,有可能是自己应用之间的Activity跳转,或者夹带其他应用的可复用Activity。可能会希望跳转到原来某个Activity实例,而不是产生大量重复的Activity。 
      这需要为Activity配置特定的加载模式,而不是使用默认的加载模式。 加载模式分类及在哪里配置 
      Activity有四种加载模式: 
       
       standard 
       singleTop</div>
                                      </li>
                                      <li><a href="/article/1103.htm"
                                             title="hibernate几个核心API及其查询分析" target="_blank">hibernate几个核心API及其查询分析</a>
                                          <span class="text-muted">antonyup_2006</span>
      <a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/.net/1.htm">.net</a><a class="tag" taget="_blank" href="/search/Hibernate/1.htm">Hibernate</a><a class="tag" taget="_blank" href="/search/xml/1.htm">xml</a><a class="tag" taget="_blank" href="/search/%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86/1.htm">配置管理</a>
                                          <div>(一)  org.hibernate.cfg.Configuration类 
              读取配置文件并创建唯一的SessionFactory对象.(一般,程序初始化hibernate时创建.) 
              Configuration co</div>
                                      </li>
                                      <li><a href="/article/1230.htm"
                                             title="PL/SQL的流程控制" target="_blank">PL/SQL的流程控制</a>
                                          <span class="text-muted">百合不是茶</span>
      <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/PL%2FSQL%E7%BC%96%E7%A8%8B/1.htm">PL/SQL编程</a><a class="tag" taget="_blank" href="/search/%E5%BE%AA%E7%8E%AF%E6%8E%A7%E5%88%B6/1.htm">循环控制</a>
                                          <div>PL/SQL也是一门高级语言,所以流程控制是必须要有的,oracle数据库的pl/sql比sqlserver数据库要难,很多pl/sql中有的sqlserver里面没有 
        
      流程控制; 
         分支语句 if 条件 then 结果 else 结果  end if ;
      
        条件语句 case    when   条件  then  结果;
      
         循环语句  loop    </div>
                                      </li>
                                      <li><a href="/article/1357.htm"
                                             title="强大的Mockito测试框架" target="_blank">强大的Mockito测试框架</a>
                                          <span class="text-muted">bijian1013</span>
      <a class="tag" taget="_blank" href="/search/mockito/1.htm">mockito</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/1.htm">单元测试</a>
                                          <div>一.自动生成Mock类        在需要Mock的属性上标记@Mock注解,然后@RunWith中配置Mockito的TestRunner或者在setUp()方法中显示调用MockitoAnnotations.initMocks(this);生成Mock类即可。二.自动注入Mock类到被测试类  &nbs</div>
                                      </li>
                                      <li><a href="/article/1484.htm"
                                             title="精通Oracle10编程SQL(11)开发子程序" target="_blank">精通Oracle10编程SQL(11)开发子程序</a>
                                          <span class="text-muted">bijian1013</span>
      <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/plsql/1.htm">plsql</a>
                                          <div>/*
       *开发子程序
       */
      --子程序目是指被命名的PL/SQL块,这种块可以带有参数,可以在不同应用程序中多次调用
      --PL/SQL有两种类型的子程序:过程和函数
      --开发过程
      --建立过程:不带任何参数
      CREATE OR REPLACE PROCEDURE out_time
      IS
      BEGIN
       DBMS_OUTPUT.put_line(systimestamp);
      E</div>
                                      </li>
                                      <li><a href="/article/1611.htm"
                                             title="【EhCache一】EhCache版Hello World" target="_blank">【EhCache一】EhCache版Hello World</a>
                                          <span class="text-muted">bit1129</span>
      <a class="tag" taget="_blank" href="/search/Hello+world/1.htm">Hello world</a>
                                          <div>本篇是EhCache系列的第一篇,总体介绍使用EhCache缓存进行CRUD的API的基本使用,更细节的内容包括EhCache源代码和设计、实现原理在接下来的文章中进行介绍 
        环境准备 
      1.新建Maven项目 
        
      2.添加EhCache的Maven依赖 
              <dependency>
                  <groupId>ne</div>
                                      </li>
                                      <li><a href="/article/1738.htm"
                                             title="学习EJB3基础知识笔记" target="_blank">学习EJB3基础知识笔记</a>
                                          <span class="text-muted">白糖_</span>
      <a class="tag" taget="_blank" href="/search/bean/1.htm">bean</a><a class="tag" taget="_blank" href="/search/Hibernate/1.htm">Hibernate</a><a class="tag" taget="_blank" href="/search/jboss/1.htm">jboss</a><a class="tag" taget="_blank" href="/search/webservice/1.htm">webservice</a><a class="tag" taget="_blank" href="/search/ejb/1.htm">ejb</a>
                                          <div>最近项目进入系统测试阶段,全赖袁大虾领导有力,保持一周零bug记录,这也让自己腾出不少时间补充知识。花了两天时间把“传智播客EJB3.0”看完了,EJB基本的知识也有些了解,在这记录下EJB的部分知识,以供自己以后复习使用。 
        
      EJB是sun的服务器端组件模型,最大的用处是部署分布式应用程序。EJB (Enterprise JavaBean)是J2EE的一部分,定义了一个用于开发基</div>
                                      </li>
                                      <li><a href="/article/1865.htm"
                                             title="angular.bootstrap" target="_blank">angular.bootstrap</a>
                                          <span class="text-muted">boyitech</span>
      <a class="tag" taget="_blank" href="/search/AngularJS/1.htm">AngularJS</a><a class="tag" taget="_blank" href="/search/AngularJS+API/1.htm">AngularJS API</a><a class="tag" taget="_blank" href="/search/angular%E4%B8%AD%E6%96%87api/1.htm">angular中文api</a>
                                          <div>angular.bootstrap 
      描述:  
          手动初始化angular。 
          这个函数会自动检测创建的module有没有被加载多次,如果有则会在浏览器的控制台打出警告日志,并且不会再次加载。这样可以避免在程序运行过程中许多奇怪的问题发生。 
          使用方法:       angular .</div>
                                      </li>
                                      <li><a href="/article/1992.htm"
                                             title="java-谷歌面试题-给定一个固定长度的数组,将递增整数序列写入这个数组。当写到数组尾部时,返回数组开始重新写,并覆盖先前写过的数" target="_blank">java-谷歌面试题-给定一个固定长度的数组,将递增整数序列写入这个数组。当写到数组尾部时,返回数组开始重新写,并覆盖先前写过的数</a>
                                          <span class="text-muted">bylijinnan</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                                          <div>
      
      public class SearchInShiftedArray {
      
      	/**
      	 * 题目:给定一个固定长度的数组,将递增整数序列写入这个数组。当写到数组尾部时,返回数组开始重新写,并覆盖先前写过的数。
      	 * 请在这个特殊数组中找出给定的整数。
      	 * 解答:
      	 * 其实就是“旋转数组”。旋转数组的最小元素见http://bylijinnan.iteye.com/bl</div>
                                      </li>
                                      <li><a href="/article/2119.htm"
                                             title="天使还是魔鬼?都是我们制造" target="_blank">天使还是魔鬼?都是我们制造</a>
                                          <span class="text-muted">ducklsl</span>
      <a class="tag" taget="_blank" href="/search/%E7%94%9F%E6%B4%BB/1.htm">生活</a><a class="tag" taget="_blank" href="/search/%E6%95%99%E8%82%B2/1.htm">教育</a><a class="tag" taget="_blank" href="/search/%E6%83%85%E6%84%9F/1.htm">情感</a>
                                          <div>----------------------------剧透请原谅,有兴趣的朋友可以自己看看电影,互相讨论哦!!! 
          从厦门回来的动车上,无意中瞟到了书中推荐的几部关于儿童的电影。当然,这几部电影可能会另大家失望,并不是类似小鬼当家的电影,而是关于“坏小孩”的电影! 
          自己挑了两部先看了看,但是发现看完之后,心里久久不能平</div>
                                      </li>
                                      <li><a href="/article/2246.htm"
                                             title="[机器智能与生物]研究生物智能的问题" target="_blank">[机器智能与生物]研究生物智能的问题</a>
                                          <span class="text-muted">comsci</span>
      <a class="tag" taget="_blank" href="/search/%E7%94%9F%E7%89%A9/1.htm">生物</a>
                                          <div> 
       
            我想,人的神经网络和苍蝇的神经网络,并没有本质的区别...就是大规模拓扑系统和中小规模拓扑分析的区别.... 
       
       
            但是,如果去研究活体人类的神经网络和脑系统,可能会受到一些法律和道德方面的限制,而且研究结果也不一定可靠,那么希望从事生物神经网络研究的朋友,不如把</div>
                                      </li>
                                      <li><a href="/article/2373.htm"
                                             title="获取Android Device的信息" target="_blank">获取Android Device的信息</a>
                                          <span class="text-muted">dai_lm</span>
      <a class="tag" taget="_blank" href="/search/android/1.htm">android</a>
                                          <div>
      String phoneInfo = "PRODUCT: " + android.os.Build.PRODUCT;
      phoneInfo += ", CPU_ABI: " + android.os.Build.CPU_ABI;
      phoneInfo += ", TAGS: " + android.os.Build.TAGS;
      ph</div>
                                      </li>
                                      <li><a href="/article/2500.htm"
                                             title="最佳字符串匹配算法(Damerau-Levenshtein距离算法)的Java实现" target="_blank">最佳字符串匹配算法(Damerau-Levenshtein距离算法)的Java实现</a>
                                          <span class="text-muted">datamachine</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%B9%E9%85%8D/1.htm">字符串匹配</a>
                                          <div>原文:http://www.javacodegeeks.com/2013/11/java-implementation-of-optimal-string-alignment.html------------------------------------------------------------------------------------------------------------</div>
                                      </li>
                                      <li><a href="/article/2627.htm"
                                             title="小学5年级英语单词背诵第一课" target="_blank">小学5年级英语单词背诵第一课</a>
                                          <span class="text-muted">dcj3sjt126com</span>
      <a class="tag" taget="_blank" href="/search/english/1.htm">english</a><a class="tag" taget="_blank" href="/search/word/1.htm">word</a>
                                          <div>long 长的 
      show 给...看,出示 
      mouth 口,嘴 
      write 写 
        
      use 用,使用 
      take 拿,带来 
      hand 手 
      clever 聪明的 
        
      often 经常 
      wash 洗 
      slow 慢的 
      house 房子 
        
      water 水 
      clean 清洁的 
      supper 晚餐 
      out 在外 
        
      face 脸,</div>
                                      </li>
                                      <li><a href="/article/2754.htm"
                                             title="macvim的使用实战" target="_blank">macvim的使用实战</a>
                                          <span class="text-muted">dcj3sjt126com</span>
      <a class="tag" taget="_blank" href="/search/mac/1.htm">mac</a><a class="tag" taget="_blank" href="/search/vim/1.htm">vim</a>
                                          <div>macvim用的是mac里面的vim, 只不过是一个GUI的APP, 相当于一个壳 
        
      1. 下载macvim 
      https://code.google.com/p/macvim/ 
        
      2. 了解macvim 
      :h               vim的使用帮助信息 
      :h macvim  </div>
                                      </li>
                                      <li><a href="/article/2881.htm"
                                             title="java二分法查找" target="_blank">java二分法查找</a>
                                          <span class="text-muted">蕃薯耀</span>
      <a class="tag" taget="_blank" href="/search/java%E4%BA%8C%E5%88%86%E6%B3%95%E6%9F%A5%E6%89%BE/1.htm">java二分法查找</a><a class="tag" taget="_blank" href="/search/%E4%BA%8C%E5%88%86%E6%B3%95/1.htm">二分法</a><a class="tag" taget="_blank" href="/search/java%E4%BA%8C%E5%88%86%E6%B3%95/1.htm">java二分法</a>
                                          <div>java二分法查找 
      >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
      蕃薯耀 2015年6月23日 11:40:03 星期二 
      http:/</div>
                                      </li>
                                      <li><a href="/article/3008.htm"
                                             title="Spring Cache注解+Memcached" target="_blank">Spring Cache注解+Memcached</a>
                                          <span class="text-muted">hanqunfeng</span>
      <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/memcached/1.htm">memcached</a>
                                          <div>Spring3.1 Cache注解  
      依赖jar包: 
      <!-- simple-spring-memcached -->
      		<dependency>
      			<groupId>com.google.code.simple-spring-memcached</groupId>
      			<artifactId>simple-s</div>
                                      </li>
                                      <li><a href="/article/3135.htm"
                                             title="apache commons io包快速入门" target="_blank">apache commons io包快速入门</a>
                                          <span class="text-muted">jackyrong</span>
      <a class="tag" taget="_blank" href="/search/apache+commons/1.htm">apache commons</a>
                                          <div>原文参考 
      http://www.javacodegeeks.com/2014/10/apache-commons-io-tutorial.html 
       
        Apache Commons IO 包绝对是好东西,地址在http://commons.apache.org/proper/commons-io/,下面用例子分别介绍: 
        1)  工具类 
        2</div>
                                      </li>
                                      <li><a href="/article/3262.htm"
                                             title="如何学习编程" target="_blank">如何学习编程</a>
                                          <span class="text-muted">lampcy</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a><a class="tag" taget="_blank" href="/search/C%2B%2B/1.htm">C++</a><a class="tag" taget="_blank" href="/search/c/1.htm">c</a>
                                          <div>首先,我想说一下学习思想.学编程其实跟网络游戏有着类似的效果.开始的时候,你会对那些代码,函数等产生很大的兴趣,尤其是刚接触编程的人,刚学习第一种语言的人.可是,当你一步步深入的时候,你会发现你没有了以前那种斗志.就好象你在玩韩国泡菜网游似的,玩到一定程度,每天就是练级练级,完全是一个想冲到高级别的意志力在支持着你.而学编程就更难了,学了两个月后,总是觉得你好象全都学会了,却又什么都做不了,又没有</div>
                                      </li>
                                      <li><a href="/article/3389.htm"
                                             title="架构师之spring-----spring3.0新特性的bean加载控制@DependsOn和@Lazy" target="_blank">架构师之spring-----spring3.0新特性的bean加载控制@DependsOn和@Lazy</a>
                                          <span class="text-muted">nannan408</span>
      <a class="tag" taget="_blank" href="/search/Spring3/1.htm">Spring3</a>
                                          <div>1.前言。 
         如题。 
      2.描述。 
         
      
      
      @DependsOn用于强制初始化其他Bean。可以修饰Bean类或方法,使用该Annotation时可以指定一个字符串数组作为参数,每个数组元素对应于一个强制初始化的Bean。
      
      @DependsOn({"steelAxe","abc"})
      @Comp</div>
                                      </li>
                                      <li><a href="/article/3516.htm"
                                             title="Spring4+quartz2的配置和代码方式调度" target="_blank">Spring4+quartz2的配置和代码方式调度</a>
                                          <span class="text-muted">Everyday都不同</span>
      <a class="tag" taget="_blank" href="/search/%E4%BB%A3%E7%A0%81/1.htm">代码</a><a class="tag" taget="_blank" href="/search/%E9%85%8D%E7%BD%AE/1.htm">配置</a><a class="tag" taget="_blank" href="/search/spring4/1.htm">spring4</a><a class="tag" taget="_blank" href="/search/quartz2.x/1.htm">quartz2.x</a><a class="tag" taget="_blank" href="/search/%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1/1.htm">定时任务</a>
                                          <div>前言:这些天简直被quartz虐哭。。因为quartz 2.x版本相比quartz1.x版本的API改动太多,所以,只好自己去查阅底层API…… 
        
      quartz定时任务必须搞清楚几个概念: 
      JobDetail——处理类 
      Trigger——触发器,指定触发时间,必须要有JobDetail属性,即触发对象 
      Scheduler——调度器,组织处理类和触发器,配置方式一般只需指定触发</div>
                                      </li>
                                      <li><a href="/article/3643.htm"
                                             title="Hibernate入门" target="_blank">Hibernate入门</a>
                                          <span class="text-muted">tntxia</span>
      <a class="tag" taget="_blank" href="/search/Hibernate/1.htm">Hibernate</a>
                                          <div>  
      前言 
        
      使用面向对象的语言和关系型的数据库,开发起来很繁琐,费时。由于现在流行的数据库都不面向对象。Hibernate 是一个Java的ORM(Object/Relational Mapping)解决方案。 
        
      Hibernte不仅关心把Java对象对应到数据库的表中,而且提供了请求和检索的方法。简化了手工进行JDBC操作的流程。 
        
      如</div>
                                      </li>
                                      <li><a href="/article/3770.htm"
                                             title="Math类" target="_blank">Math类</a>
                                          <span class="text-muted">xiaoxing598</span>
      <a class="tag" taget="_blank" href="/search/Math/1.htm">Math</a>
                                          <div>一、Java中的数字(Math)类是final类,不可继承。 
      1、常数    PI:double圆周率 E:double自然对数    
      2、截取(注意方法的返回类型)    double ceil(double d) 返回不小于d的最小整数 double floor(double d) 返回不大于d的整最大数   int round(float f) 返回四舍五入后的整数 long round</div>
                                      </li>
                      </ul>
                  </div>
              </div>
          </div>
      
      <div>
          <div class="container">
              <div class="indexes">
                  <strong>按字母分类:</strong>
                  <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a
                      href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a
                      href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a
                      href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a
                      href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a
                      href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a
                      href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a
                      href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a
                      href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a>
              </div>
          </div>
      </div>
      <footer id="footer" class="mb30 mt30">
          <div class="container">
              <div class="footBglm">
                  <a target="_blank" href="/">首页</a> -
                  <a target="_blank" href="/custom/about.htm">关于我们</a> -
                  <a target="_blank" href="/search/Java/1.htm">站内搜索</a> -
                  <a target="_blank" href="/sitemap.txt">Sitemap</a> -
                  <a target="_blank" href="/custom/delete.htm">侵权投诉</a>
              </div>
              <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved.
      <!--            <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>-->
              </div>
          </div>
      </footer>
      <!-- 代码高亮 -->
      <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script>
      <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script>
      <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script>
      <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/>
      <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script>
      
      
      
      
      
      </body>
      
      </html>