<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Python on 中二青年</title>
    <link>https://zhong-er.com/categories/python/</link>
    <description>Recent content in Python on 中二青年</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Fri, 25 Oct 2019 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://zhong-er.com/categories/python/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>【DRF】 django rest framework总结</title>
      <link>https://zhong-er.com/posts/drf-django-rest-framework%E6%80%BB%E7%BB%93/</link>
      <pubDate>Fri, 25 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/drf-django-rest-framework%E6%80%BB%E7%BB%93/</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;img alt=&#34;drf.jpg&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201910177473_80_1.jpg&#34;&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id=&#34;1接口&#34;&gt;1.接口**&lt;/h1&gt;
&lt;p&gt;**&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;
1、什么是接口：url+请求参数+响应数据 | 接口文档

2、接口规范：
	url：https，api，资源(名词复数)，v1，get|post表示操作资源的方式，?过滤条件
	响应数据：status，msg，results|data，url资源数据
&amp;quot;&amp;quot;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;2drf入门&#34;&gt;2.DRF入门&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;
1、封装风格

2、请求生命周期：走APIView的as_view =&amp;gt; View的as_view调用APIView的dispatch =&amp;gt; 分发给视图类的请求函数 =&amp;gt; 响应

3、请求模块：二次封装request

4、解析模块：局部全局配置，form-data、urlencoding、json

5、渲染模块：局部全局配置，html、json

6、响应模块：Response(data, http_status, header)
data={&#39;detail&#39;: serializer_obj.errors} =&amp;gt; http_status=4..|5..
# 4,5开头字段状态码，前台axios请求响应会解析到catch分支
axios({}).then().catch()

7、二次封装Response：
	i) 继承Response
	ii) 自定义参数格式化成data，传给 super().__init__(data=data)
	iii) 网络状态码、响应头等信息带给super().__init__()
	
8、异常模块：在请求生命周期中，分发请求任务执行时，被一个超大的try except包裹，一旦出现任何异常，都会交给exception_handler函数处理
	自定义原因：系统只处理了部分，所以手动还需要处理；后期异常信息需要记录到日志文件
	工作流程：先交给drf处理异常，如果有响应结果，代表drf已处理，如果是None，自己处理
&amp;quot;&amp;quot;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;3序列化组件&#34;&gt;3.序列化组件**&lt;/h1&gt;
&lt;p&gt;**&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 1）可以将model对象序列化成可以返回给前台的json数据
# 2）可以校验前台传来的数据，完成model的增与改
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;模型层&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class User(models.Model):
    name = models.CharField(max_length=16)
    
    # 自定义插拔序列化字段 - 完成连表深度查询
    @property
    def my_name(self):
        return self.name
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;序列化层&lt;/p&gt;</description>
    </item>
    <item>
      <title>【DRF】偏移分页组件/游标分页组件/自定义过滤器/过滤器插件</title>
      <link>https://zhong-er.com/posts/drf%E5%81%8F%E7%A7%BB%E5%88%86%E9%A1%B5%E7%BB%84%E4%BB%B6%E6%B8%B8%E6%A0%87%E5%88%86%E9%A1%B5%E7%BB%84%E4%BB%B6%E8%87%AA%E5%AE%9A%E4%B9%89%E8%BF%87%E6%BB%A4%E5%99%A8%E8%BF%87%E6%BB%A4%E5%99%A8%E6%8F%92%E4%BB%B6/</link>
      <pubDate>Fri, 25 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/drf%E5%81%8F%E7%A7%BB%E5%88%86%E9%A1%B5%E7%BB%84%E4%BB%B6%E6%B8%B8%E6%A0%87%E5%88%86%E9%A1%B5%E7%BB%84%E4%BB%B6%E8%87%AA%E5%AE%9A%E4%B9%89%E8%BF%87%E6%BB%A4%E5%99%A8%E8%BF%87%E6%BB%A4%E5%99%A8%E6%8F%92%E4%BB%B6/</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;img alt=&#34;drf.jpg&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201910177473_80_1.jpg&#34;&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id=&#34;1drf偏移分页组件&#34;&gt;1.drf偏移分页组件&lt;/h1&gt;
&lt;p&gt;pahenations.py&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from rest_framework.pagination import LimitOffsetPagination
class MyLimitOffsetPagination(LimitOffsetPagination):
    # ?offset=从头偏移的条数&amp;amp;limit=要显示的条数
    limit_query_param = &#39;limit&#39;
    offset_query_param = &#39;offset&#39;
    # ?不传offset和limit默认显示前3条，只设置offset就是从偏移位往后再显示3条
    default_limit = 3
    # ?limit可以自定义一页显示的最大条数
    max_limit = 5

    # 只使用limit结合ordering可以实现排行前几或后几
    # ?ordering=-price&amp;amp;limit=2  =&amp;gt; 价格前2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;views.py&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from rest_framework.generics import ListAPIView

class CarListAPIView(ListAPIView):
    # 如果queryset没有过滤条件，就必须 .all()，不然分页会出问题
    queryset = models.Car.objects.all()
    serializer_class = serializers.CarModelSerializer
    
    # 分页组件 - 给视图类配置分页类即可 - 分页类需要自定义，继承drf提供的分页类即可
    pagination_class = pagenations.MyLimitOffsetPagination
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;2drf游标分页组件&#34;&gt;2.drf游标分页组件&lt;/h1&gt;
&lt;p&gt;pahenations.py&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 注：必须基于排序规则下进行分页
# 1）如果接口配置了OrderingFilter过滤器，那么url中必须传ordering
# 1）如果接口没有配置OrderingFilter过滤器，一定要在分页类中声明ordering按某个字段进行默认排序
from rest_framework.pagination import CursorPagination
class MyCursorPagination(CursorPagination):
    cursor_query_param = &#39;cursor&#39;
    page_size = 3
    page_size_query_param = &#39;page_size&#39;
    max_page_size = 5
    ordering = &#39;-pk&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;views.py&lt;/p&gt;</description>
    </item>
    <item>
      <title>【DRF】频率组件</title>
      <link>https://zhong-er.com/posts/drf%E9%A2%91%E7%8E%87%E7%BB%84%E4%BB%B6/</link>
      <pubDate>Tue, 22 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/drf%E9%A2%91%E7%8E%87%E7%BB%84%E4%BB%B6/</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;img alt=&#34;drf.jpg&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201910177473_80_1.jpg&#34;&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id=&#34;1频率类源码入口&#34;&gt;&lt;strong&gt;1.频率类源码入口&lt;/strong&gt;&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;# 1）APIView的dispath方法中的 self.initial(request, *args, **kwargs) 点进去
# 2）self.check_throttles(request) 进行频率认证

# 频率组件核心源码分析
def check_throttles(self, request):
    throttle_durations = []
    # 1）遍历配置的频率认证类，初始化得到一个个频率认证类对象（会调用频率认证类的 __init__() 方法）
    # 2）频率认证类对象调用 allow_request 方法，判断是否限次（没有限次可访问，限次不可访问）
    # 3）频率认证类对象在限次后，调用 wait 方法，获取还需等待多长时间可以进行下一次访问
    # 注：频率认证类都是继承 SimpleRateThrottle 类
    for throttle in self.get_throttles():
        if not throttle.allow_request(request, self):
            # 只要频率限制了，allow_request 返回False了，才会调用wait
            throttle_durations.append(throttle.wait())

            if throttle_durations:
                # Filter out `None` values which may happen in case of config / rate
                # changes, see #1438
                durations = [
                    duration for duration in throttle_durations
                    if duration is not None
                ]

                duration = max(durations, default=None)
                self.throttled(request, duration)
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;2自定义频率类&#34;&gt;&lt;strong&gt;2.自定义频率类&lt;/strong&gt;&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;# 1) 自定义一个继承 SimpleRateThrottle 类 的频率类
# 2) 设置一个 scope 类属性，属性值为任意见名知意的字符串
# 3) 在settings配置文件中，配置drf的DEFAULT_THROTTLE_RATES，格式为 {scope字符串: &#39;次数/时间&#39;}
# 4) 在自定义频率类中重写 get_cache_key 方法
	# 限制的对象返回 与限制信息有关的字符串
    # 不限制的对象返回 None (只能放回None，不能是False或是&#39;&#39;等)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;短信接口1/min频率限制&lt;/p&gt;</description>
    </item>
    <item>
      <title>【DRF】认证组件/权限组件</title>
      <link>https://zhong-er.com/posts/drf%E8%AE%A4%E8%AF%81%E7%BB%84%E4%BB%B6%E6%9D%83%E9%99%90%E7%BB%84%E4%BB%B6/</link>
      <pubDate>Mon, 21 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/drf%E8%AE%A4%E8%AF%81%E7%BB%84%E4%BB%B6%E6%9D%83%E9%99%90%E7%BB%84%E4%BB%B6/</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;img alt=&#34;drf.jpg&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201910177473_80_1.jpg&#34;&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;三大认证源码分析&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1）APIView的dispath(self, request, *args, **kwargs)
2）dispath方法内 self.initial(request, *args, **kwargs) 进入三大认证
	# 认证组件：校验用户 - 游客、合法用户、非法用户
    # 游客：代表校验通过，直接进入下一步校验（权限校验）
    # 合法用户：代表校验通过，将用户存储在request.user中，再进入下一步校验（权限校验）
    # 非法用户：代表校验失败，抛出异常，返回403权限异常结果
    self.perform_authentication(request)
    
    # 权限组件：校验用户权限 - 必须登录、所有用户、登录读写游客只读、自定义用户角色
    # 认证通过：可以进入下一步校验（频率认证）
    # 认证失败：抛出异常，返回403权限异常结果
    self.check_permissions(request)
    
    # 频率组件：限制视图接口被访问的频率次数 - 限制的条件(IP、id、唯一键)、频率周期时间(s、m、h)、频率的次数（3/s）
    # 没有达到限次：正常访问接口
    # 达到限次：限制时间内不能访问，限制时间达到后，可以重新访问
    self.check_throttles(request)
    
    
3) 认证组件
	Request类的 方法属性 user 的get方法 =&amp;gt; self._authenticate() 完成认证
	
	认证的细则：
	# 做认证
    def _authenticate(self):
        # 遍历拿到一个个认证器，进行认证
        # self.authenticators配置的一堆认证类产生的认证类对象组成的 list
        for authenticator in self.authenticators:
            try:
                # 认证器(对象)调用认证方法authenticate(认证类对象self, request请求对象)
                # 返回值：登陆的用户与认证的信息组成的 tuple
                # 该方法被try包裹，代表该方法会抛异常，抛异常就代表认证失败
                user_auth_tuple = authenticator.authenticate(self)
            except exceptions.APIException:
                self._not_authenticated()
                raise

            # 返回值的处理
            if user_auth_tuple is not None:
                self._authenticator = authenticator
                # 如何有返回值，就将 登陆用户 与 登陆认证 分别保存到 request.user、request.auth
                self.user, self.auth = user_auth_tuple
                return
        # 如果返回值user_auth_tuple为空，代表认证通过，但是没有 登陆用户 与 登陆认证信息，代表游客
        self._not_authenticated()

4) 权限组件
	self.check_permissions(request)
	认证细则：
    def check_permissions(self, request):
        # 遍历权限对象列表得到一个个权限对象(权限器)，进行权限认证
        for permission in self.get_permissions():
            # 权限类一定有一个has_permission权限方法，用来做权限认证的
            # 参数：权限对象self、请求对象request、视图类对象
            # 返回值：有权限返回True，无权限返回False
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request, message=getattr(permission, &#39;message&#39;, None)
                )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;自定义认证类&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【DRF】视图家族</title>
      <link>https://zhong-er.com/posts/drf%E8%A7%86%E5%9B%BE%E5%AE%B6%E6%97%8F/</link>
      <pubDate>Mon, 21 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/drf%E8%A7%86%E5%9B%BE%E5%AE%B6%E6%97%8F/</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;img alt=&#34;drf.jpg&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201910177473_80_1.jpg&#34;&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;视图类传递参数给序列化类&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1）在视图类中实例化序列化对象时，可以设置context内容
2）在序列化类中的局部钩子、全局钩子、create、update方法中，都可以用self.context访问视图类传递过来的内容

需求：
1) 在视图类中，可以通过request得到登陆用户request.user
2) 在序列化类中，要完成数据库数据的校验与入库操作，可能会需要知道当前的登陆用户，但序列化类无法访问request
3) 在视图类中实例化序列化对象时，将request对象传递进去
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;视图层：views.py&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Book(APIView):
    def post(self, request, *args, **kwargs):
        book_ser = serializers.BookModelSerializer(data=request_data,context={&#39;request&#39;:request})
        book_ser.is_valid(raise_exception=True)
        book_result = book_ser.save()
        return Response({
            &#39;status&#39;: 0,
            &#39;msg&#39;: &#39;ok&#39;,
            &#39;results&#39;: serializers.BookModelSerializer(book_result).data
        })
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;序列化层：serializer.py&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class BookModelSerializer(ModelSerializer):
    class Meta:
        model = models.Book
        fields = (&#39;name&#39;, &#39;price&#39;)
    def validate_name(self, value):
        print(self.context.get(&#39;request&#39;).method)
        return value
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;二次封装Response类&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Response({
    &#39;status&#39;: 0,
    &#39;msg&#39;: &#39;ok&#39;,
    &#39;results&#39;: [],
    &#39;token&#39;: &#39;&#39;  # 有这样的额外的key-value数据结果
},status=http_status,headers=headers,exception=True|False)

APIResponse() =&amp;gt; Response({&#39;status&#39;: 0,&#39;msg&#39;: &#39;ok&#39;})


from rest_framework.response import Response

class APIResponse(Response):
    def __init__(self, data_status=0, data_msg=&#39;ok&#39;, results=None, http_status=None, headers=None, exception=False, **kwargs):
        # data的初始状态：状态码与状态信息
        data = {
            &#39;status&#39;: data_status,
            &#39;msg&#39;: data_msg,
        }
        # data的响应数据体
        # results可能是False、0等数据，这些数据某些情况下也会作为合法数据返回
        if results is not None:
            data[&#39;results&#39;] = results
        # data响应的其他内容
        # if kwargs is not None:
        #     for k, v in kwargs.items():
        #         setattr(data, k, v)
        data.update(kwargs)

        super().__init__(data=data, status=http_status, headers=headers, exception=exception)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;视图家族&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【DRF】接口/CBV生命周期</title>
      <link>https://zhong-er.com/posts/drf%E6%8E%A5%E5%8F%A3cbv%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/</link>
      <pubDate>Thu, 17 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/drf%E6%8E%A5%E5%8F%A3cbv%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;img alt=&#34;drf.jpg&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201910177473_80_1.jpg&#34;&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DRF框架&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;全称：Django-rest framework&lt;/p&gt;
&lt;p&gt;知识点&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;
1、接口：什么是接口、restful接口规范
2、CBV生命周期源码 - 基于restful规范下的CBV接口
3、请求组件、解析组件、响应组件
4、序列化组件(灵魂)
5、三大认证(重中之重)：认证、权限(权限六表)、频率
6、其他组件：过滤、筛选、排序、分页、路由
&amp;quot;&amp;quot;&amp;quot;

# 难点：源码分析
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;接口&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;
接口：联系两个物质的媒介，完成信息交互
web程序中：联系前台页面与后台数据库的媒介
web接口组成：
	url：长得像放回数据的url链接
	请求参数：前台按照指定的key提供数据给后台
	响应数据：后台与数据库交互后将数据反馈给前台
&amp;quot;&amp;quot;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;restful接口规范&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;接口规范：就是为了采用不同的后台语言，也能使用同样的接口获取到同样的数据&lt;/p&gt;
&lt;p&gt;如何写接口：接口规范是规范化书写接口，写接口要写url、响应数据&lt;/p&gt;
&lt;p&gt;注：如果将请求参数也纳入考量范围，那就是在写接口文档&lt;/p&gt;
&lt;p&gt;两大部分：&lt;/p&gt;
&lt;p&gt;url&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1) 用api关键字表示接口url
    api.baidu.com | www.baidu.com/api
	
2) 接口数据安全性决定优先选择https协议

3) 如果一个接口有多版本存在，需要在url中标识体现
    api.baidu.com/v1/... | api.baidu.com/v2/...
	
4) 接口操作的数据源称之为 资源，在url中一般采用资源复数形式，一个接口可以概括对该资源的多种操作方式
    api.baidu.com/books | api.baidu.com/books/(pk)
	
5) 请求方式有多种，用一个url处理如何保证不混乱 - 通过请求方式标识操作资源的方式
    /books		get			获取所有
    /books		post		增加一个(多个)
    /books/(pk)	delete		删除一个
    /books/(pk)	put			整体更新一个
    /books/(pk)	patch		局部更新一个

6) 资源往往涉及数据的各种操作方式 - 筛选、排序、限制
	api.baidu.com/books/?search=西&amp;amp;ordering=-price&amp;amp;limit=3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;响应数据&lt;/p&gt;</description>
    </item>
    <item>
      <title>【DRF】解析/异常/响应模块/序列化组件</title>
      <link>https://zhong-er.com/posts/drf%E8%A7%A3%E6%9E%90%E5%BC%82%E5%B8%B8%E5%93%8D%E5%BA%94%E6%A8%A1%E5%9D%97%E5%BA%8F%E5%88%97%E5%8C%96%E7%BB%84%E4%BB%B6/</link>
      <pubDate>Thu, 17 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/drf%E8%A7%A3%E6%9E%90%E5%BC%82%E5%B8%B8%E5%93%8D%E5%BA%94%E6%A8%A1%E5%9D%97%E5%BA%8F%E5%88%97%E5%8C%96%E7%BB%84%E4%BB%B6/</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;img alt=&#34;drf.jpg&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201910177473_80_1.jpg&#34;&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解析模块&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为什么要配置解析模块&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;
1）drf给我们通过了多种解析数据包方式的解析类
2）我们可以通过配置来控制前台提交的哪些格式的数据后台在解析，哪些数据不解析
3）全局配置就是针对每一个视图类，局部配置就是针对指定的视图来，让它们可以按照配置规则选择性解析数据
&amp;quot;&amp;quot;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;源码入口&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# APIView类的dispatch方法中
request = self.initialize_request(request, *args, **kwargs)  # 点进去

# 获取解析类
parsers=self.get_parsers(),  # 点进去

# 去类属性(局部配置) 或 配置文件(全局配置) 拿 parser_classes
return [parser() for parser in self.parser_classes]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;全局配置：项目settings.py文件&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;REST_FRAMEWORK = {
    # 全局解析类配置
    &#39;DEFAULT_PARSER_CLASSES&#39;: [
        &#39;rest_framework.parsers.JSONParser&#39;,  # json数据包
        &#39;rest_framework.parsers.FormParser&#39;,  # urlencoding数据包
        &#39;rest_framework.parsers.MultiPartParser&#39;  # form-date数据包
    ],
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;局部配置：应用views.p的具体视图类&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from rest_framework.parsers import JSONParser
class Book(APIView):
    # 局部解析类配置，只要json类型的数据包才能被解析
    parser_classes = [JSONParser]
    pass
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;异常模块&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【DRF】序列化/反序列/序列化与反序列整合</title>
      <link>https://zhong-er.com/posts/drf%E5%BA%8F%E5%88%97%E5%8C%96%E5%8F%8D%E5%BA%8F%E5%88%97%E5%BA%8F%E5%88%97%E5%8C%96%E4%B8%8E%E5%8F%8D%E5%BA%8F%E5%88%97%E6%95%B4%E5%90%88/</link>
      <pubDate>Thu, 17 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/drf%E5%BA%8F%E5%88%97%E5%8C%96%E5%8F%8D%E5%BA%8F%E5%88%97%E5%BA%8F%E5%88%97%E5%8C%96%E4%B8%8E%E5%8F%8D%E5%BA%8F%E5%88%97%E6%95%B4%E5%90%88/</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;img alt=&#34;drf.jpg&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201910177473_80_1.jpg&#34;&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;环境配置&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;配置：settings.py&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;INSTALLED_APPS = [
    # ...
    &#39;rest_framework&#39;,
]

DATABASES = {
    &#39;default&#39;: {
        &#39;ENGINE&#39;: &#39;django.db.backends.mysql&#39;,
        &#39;NAME&#39;: &#39;dg_proj&#39;,
        &#39;USER&#39;: &#39;root&#39;,
        &#39;PASSWORD&#39;: &#39;123&#39;,
    }
}
&amp;quot;&amp;quot;&amp;quot;
任何__init__文件
import pymysql
pymysql.install_as_MySQLdb()
&amp;quot;&amp;quot;&amp;quot;

LANGUAGE_CODE = &#39;zh-hans&#39;
TIME_ZONE = &#39;Asia/Shanghai&#39;
USE_I18N = True
USE_L10N = True
USE_TZ = False

MEDIA_URL = &#39;/media/&#39;
MEDIA_ROOT = os.path.join(BASE_DIR, &#39;media&#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;路由&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 主
from django.conf.urls import url, include
from django.contrib import admin
from django.views.static import serve
from django.conf import settings
urlpatterns = [
    url(r&#39;^admin/&#39;, admin.site.urls),
    url(r&#39;^api/&#39;, include(&#39;api.urls&#39;)),
    url(r&#39;^media/(?P&amp;lt;path&amp;gt;.*)&#39;, serve, {&#39;document_root&#39;: settings.MEDIA_ROOT}),
]

# 子
from django.conf.urls import url
from . import views
urlpatterns = [
    
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;多表设计&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Django】中间件/Auth模块</title>
      <link>https://zhong-er.com/posts/django%E4%B8%AD%E9%97%B4%E4%BB%B6auth%E6%A8%A1%E5%9D%97/</link>
      <pubDate>Wed, 25 Sep 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/django%E4%B8%AD%E9%97%B4%E4%BB%B6auth%E6%A8%A1%E5%9D%97/</guid>
      <description>&lt;p&gt;&lt;strong&gt;Django中间件&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Django中间件类似于Django的保安。请求的时候需要先经过中间件才能到达Django后端(urls,views,templates,models),响应走的时候也需要经过中间件才能到达web服务网关接口。&lt;/p&gt;
&lt;p&gt;Django默认的七个中间件&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MIDDLEWARE = [
    &#39;django.middleware.security.SecurityMiddleware&#39;,
    &#39;django.contrib.sessions.middleware.SessionMiddleware&#39;,
    &#39;django.middleware.common.CommonMiddleware&#39;,
    &#39;django.middleware.csrf.CsrfViewMiddleware&#39;,
    &#39;django.contrib.auth.middleware.AuthenticationMiddleware&#39;,
    &#39;django.contrib.messages.middleware.MessageMiddleware&#39;,
    &#39;django.middleware.clickjacking.XFrameOptionsMiddleware&#39;,
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们点进去几个组件查看源码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class SecurityMiddleware(MiddlewareMixin):
    def __init__(self, get_response=None):
        pass

    def process_request(self, request):
        path = request.path.lstrip(&amp;quot;/&amp;quot;)
        if (self.redirect and not request.is_secure() and not any(pattern.search(path) for pattern in self.redirect_exempt)):
            host = self.redirect_host or request.get_host()
            return HttpResponsePermanentRedirect(&amp;quot;https://%s%s&amp;quot; % (host, request.get_full_path()))

    def process_response(self, request, response):
        ...
        return response


class CsrfViewMiddleware(MiddlewareMixin):
    def process_request(self, request):
        pass

    def process_view(self, request, callback, callback_args, callback_kwargs):
        ...
        return self._accept(request)

    def process_response(self, request, response):
        ...
        return response

class AuthenticationMiddleware(MiddlewareMixin):    
    def process_request(self, request):
        assert hasattr(request, &#39;session&#39;), (
            &amp;quot;The Django authentication middleware requires session middleware &amp;quot;
            &amp;quot;to be installed. Edit your MIDDLEWARE%s setting to insert &amp;quot;
            &amp;quot;&#39;django.contrib.sessions.middleware.SessionMiddleware&#39; before &amp;quot;
            &amp;quot;&#39;django.contrib.auth.middleware.AuthenticationMiddleware&#39;.&amp;quot;
        ) % (&amp;quot;_CLASSES&amp;quot; if settings.MIDDLEWARE is None else &amp;quot;&amp;quot;)
        request.user = SimpleLazyObject(lambda: get_user(request))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不难发现一些规律：&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Django】form组件/cookie与session</title>
      <link>https://zhong-er.com/posts/djangoform%E7%BB%84%E4%BB%B6cookie%E4%B8%8Esession/</link>
      <pubDate>Tue, 24 Sep 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/djangoform%E7%BB%84%E4%BB%B6cookie%E4%B8%8Esession/</guid>
      <description>&lt;p&gt;**多对多三种创建方式&lt;br&gt;
**&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.全自动&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;优势：不需要你手动创建第三张表&lt;/p&gt;
&lt;p&gt;不足：由于第三张表不是你手动创建的，也就意味着第三张表字段时固定的无法做扩展&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    authors = models.ManyToManyField(to=&#39;Author&#39;)

 
class Author(models.Model):
    name = models.CharField(max_length=32)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;2.纯手动&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;自己创建第三张表&lt;/p&gt;
&lt;p&gt;优势：第三张表可以任意的扩展字段&lt;/p&gt;
&lt;p&gt;不足：orm查询不方便&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)

class Author(models.Model):
    name = models.CharField(max_length=32)

class Book2Author(models.Model):
    book = models.ForeignKey(to=&#39;Book&#39;)
    author = models.ForeignKey(to=&#39;Author&#39;)
    create_time = models.DateField(auto_now_add=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;3.半自动(推荐使用)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;优势：结合了全自动和纯手动的两个优点&lt;/p&gt;
&lt;p&gt;不足：不再支持多对多字段的add(),set(),remove(),clear()方法&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    authors = models.ManyToManyField(to=&#39;Author&#39;,through=&#39;Book2Author&#39;,through_fields=(&#39;book&#39;,&#39;author&#39;))
    # through 告诉django orm 书籍表和作者表的多对多关系是通过Book2Author来记录的
    # through_fields 告诉django orm记录关系时用过Book2Author表中的book字段和author字段来记录的

class Author(models.Model):
    name = models.CharField(max_length=32)
    # books = models.ManyToManyField(to=&#39;Book&#39;, through=&#39;Book2Author&#39;, through_fields=(&#39;author&#39;, &#39;book&#39;))

class Book2Author(models.Model):
    book = models.ForeignKey(to=&#39;Book&#39;)
    author = models.ForeignKey(to=&#39;Author&#39;)
    create_time = models.DateField(auto_now_add=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;forms组件&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Django】Ajax/序列化组件/sweetalert/分页器</title>
      <link>https://zhong-er.com/posts/djangoajax%E5%BA%8F%E5%88%97%E5%8C%96%E7%BB%84%E4%BB%B6sweetalert%E5%88%86%E9%A1%B5%E5%99%A8/</link>
      <pubDate>Mon, 23 Sep 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/djangoajax%E5%BA%8F%E5%88%97%E5%8C%96%E7%BB%84%E4%BB%B6sweetalert%E5%88%86%E9%A1%B5%E5%99%A8/</guid>
      <description>&lt;p&gt;&lt;strong&gt;choices参数&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我们存用户信息性别时，写入数据库时，写入的是数字1或2，&lt;/p&gt;
&lt;p&gt;但从数据库读取时，我们又不能直接将数字展示给用户，&lt;/p&gt;
&lt;p&gt;我们需要将1和2对应的男女展示给用户&lt;/p&gt;
&lt;p&gt;choices的定义&lt;/p&gt;
&lt;p&gt;choices参数是在models中定义&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from django.db import models
class User(models.Model):
    username = models.CharField(max_length=32)
    age = models.IntegerField()    choices = (
        (1,&#39;男&#39;),(2,&#39;女&#39;),(3,&#39;其他&#39;)
    )
    gender = models.IntegerField(choices=choices)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;choices怎么用&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;print(user_obj.get_gender_display())
# 只要是choices字段 在获取数字对应的值 
# 固定语法：get_choices字段名_display()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;choices容错&lt;/p&gt;
&lt;p&gt;比如数据库中某个用户的gender存的是4， 但是choices中没有4对应的值那么不会报错，&lt;/p&gt;
&lt;p&gt;而是展示的是数据库中存的这个值4&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;user_obj = models.User.objects.filter(name=&#39;jason&#39;).first()
print(user_obj.get_gender_display())    # 男user_obj = models.User.objects.filter(name=&#39;tank&#39;).first()
print(user_obj.get_gender_display())    # 4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;MTV和MVC模型&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;django框架 自称为是MTV框架&lt;/p&gt;
&lt;p&gt;M:models&lt;/p&gt;
&lt;p&gt;T:templates&lt;/p&gt;
&lt;p&gt;V:views&lt;/p&gt;
&lt;p&gt;MVC&lt;/p&gt;
&lt;p&gt;M:models&lt;/p&gt;
&lt;p&gt;V:views&lt;/p&gt;
&lt;p&gt;C:controller控制器(urls)&lt;/p&gt;
&lt;p&gt;本质:MTV其实也是MVC&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ajax&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;特点： 异步提交 局部刷新（比如注册页面，实时检测用户名是否已存在）&lt;/p&gt;
&lt;p&gt;目前发送请求的方式 GET POST&lt;/p&gt;
&lt;p&gt;a标签href属性 GET请求&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Django】ORM中常用字段和参数</title>
      <link>https://zhong-er.com/posts/djangoorm%E4%B8%AD%E5%B8%B8%E7%94%A8%E5%AD%97%E6%AE%B5%E5%92%8C%E5%8F%82%E6%95%B0/</link>
      <pubDate>Fri, 20 Sep 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/djangoorm%E4%B8%AD%E5%B8%B8%E7%94%A8%E5%AD%97%E6%AE%B5%E5%92%8C%E5%8F%82%E6%95%B0/</guid>
      <description>&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201909169981_9838.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;常用字段&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;常见字段&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AutoField&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;int自增列，必须填入参数primary_key=True。当model中如果没有自增列，则会自动创建一个列名为id的列。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;IntegerField&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一个整数类型，范围在-214748368to214748367。(一般不用它来存手机号，位数也不够，直接用字符串存)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CharField&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;字符类型，必须提供max_length参数，max_length表示字符长度。&lt;/p&gt;
&lt;p&gt;这里需要知道的是Django中的CharField对应的MySQL数据库中的varchar类型，没有设置对应char类型的字段，但是Django允许我们自定义新的字段，下面我们来自定义对应于数据库的char类型&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;1.png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201909207986_7402.png-zhonger.com&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;EmailField()&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;varchar(254)内部是个varchar字段**&lt;br&gt;
**&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BooleanField(Field)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;is_delete = BooleanField()&lt;/p&gt;
&lt;p&gt;给该字段传值的时候 你只需要传布尔值即可&lt;/p&gt;
&lt;p&gt;但是对应到数据库 它存的是0和1&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TextField(Field)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;- 文本类型&lt;/p&gt;
&lt;p&gt;用来存大段文本&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FileField(Field)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;- 字符串，路径保存在数据库，文件上传到指定目录&lt;/p&gt;
&lt;p&gt;- 参数：&lt;/p&gt;
&lt;p&gt;upload_to = &amp;quot;&amp;quot; 用户上传的文件会自动放到等号后面指定的文件路径中&lt;/p&gt;
&lt;p&gt;storage = None 存储组件，默django.core.files.storage.FileSystemStorage&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;自定义char字段&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from django.db import models

# Create your models here.
#Django中没有对应的char类型字段，但是我们可以自己创建
class FixCharField(models.Field):
    &#39;&#39;&#39;
    自定义的char类型的字段类
    &#39;&#39;&#39;
    def __init__(self,max_length,*args,**kwargs):
        self.max_length=max_length
        super().__init__(max_length=max_length,*args,**kwargs)

    def db_type(self, connection):
        &#39;&#39;&#39;
        限定生成的数据库表字段类型char，长度为max_length指定的值
        :param connection:
        :return:
        &#39;&#39;&#39;
        return &#39;char(%s)&#39;%self.max_length
#应用上面自定义的char类型
class Class(models.Model):
    id=models.AutoField(primary_key=True)
    title=models.CharField(max_length=32)
    class_name=FixCharField(max_length=16)
    gender_choice=((1,&#39;男&#39;),(2,&#39;女&#39;),(3,&#39;保密&#39;))
    gender=models.SmallIntegerField(choices=gender_choice,default=3)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;DateField&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Django】模型层</title>
      <link>https://zhong-er.com/posts/django%E6%A8%A1%E5%9E%8B%E5%B1%82/</link>
      <pubDate>Thu, 19 Sep 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/django%E6%A8%A1%E5%9E%8B%E5%B1%82/</guid>
      <description>&lt;p&gt;&lt;strong&gt;ORM单表操作&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;单表操作演示表&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Book(models.Model):
      name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_place=2)
    publish = models.CharField(max_length=32)
    author = models.CharField(max_length=32)
    create_time = models.DateField(null=True)
    # 配置auto_now_add=True，创建数据记录的时候会把当前时间添加到数据库。
    # 配置上auto_now=True，每次更新数据记录的时候会更新该字段。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;新增数据&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 第一种：有返回值，并且就是当前被创建的数据对象
modles.Book.objects.create(name=&#39;&#39;,price=&#39;&#39;,publish=&#39;&#39;,author=&#39;&#39;,create_time=&#39;2019-5-1&#39;)
# 第二种：先实例化产生对象，然后调用save方法保存
book_obj = models.Book(name=&#39;&#39;,price=&#39;&#39;,publish=&#39;&#39;,author=&#39;&#39;,create_time=&#39;2019-5-1&#39;)
book_obj.save()
# 2.验证时间格式字段即可以传字符串也可以传时间对象
import datetime
ctime = datetime.datetime.now()
book = models.Book.objects.create(name=&#39;&#39;,price=&#39;&#39;,author=&#39;&#39;,create_time=ctime)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;删除数据&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;删除数据&amp;quot;&amp;quot;&amp;quot;
# 1.删除书名为xxx的这本书  queryset方法
res = models.Book.objects.filter(name=&#39;&#39;).delete()
print(res)
# 2.删除书名为xxx的这本书  queryset方法
res = models.Book.objects.filter(name=&#39;&#39;).first()
res.delete()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;修改数据&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 1.queryset修改
models.Book.objects.filter(name=&#39;&#39;).update(price=&#39;&#39;)
# 2.对象修改
book = models.Book.objects.filter(name=&#39;&#39;).first()
book.price = 66.66
book.save()  # 对象只有保存方法 这样也能实现修改需求
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;查询数据的13个方法&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Django】模板层</title>
      <link>https://zhong-er.com/posts/django%E6%A8%A1%E6%9D%BF%E5%B1%82/</link>
      <pubDate>Wed, 18 Sep 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/django%E6%A8%A1%E6%9D%BF%E5%B1%82/</guid>
      <description>&lt;p&gt;&lt;strong&gt;模版语法&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;两大类&lt;/p&gt;
&lt;p&gt;{{}} 变量相关&lt;/p&gt;
&lt;p&gt;{%%} 逻辑相关&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;给模版传值&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;python所有的数据类型都可以被传递到前端页面&lt;/p&gt;
&lt;p&gt;注意在传递函数的时候，会自动加括号调用，前端展示的是函数调用的之后的返回值(ps:前端在调用函数的时候，是不支持给函数传递额外参数的)&lt;/p&gt;
&lt;p&gt;如果你想在前端获取后端传递的某个容器类型中的具体元素&lt;/p&gt;
&lt;p&gt;那么你可以通过句点符来获取具体的元素&lt;/p&gt;
&lt;p&gt;.索引&lt;/p&gt;
&lt;p&gt;.键&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;变量&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在Django的模板语言中按此语法使用：{{ 变量名 }}。&lt;/p&gt;
&lt;p&gt;当模版引擎遇到一个变量，它将计算这个变量，然后用结果替换掉它本身。 变量的命名包括任何字母数字以及下划线 (&amp;quot;_&amp;quot;)的组合。 变量名称中不能有空格或标点符号。&lt;/p&gt;
&lt;p&gt;点（.）在模板语言中有特殊的含义。当模版系统遇到点(&amp;quot;.&amp;quot;)，它将以这样的顺序查询：&lt;/p&gt;
&lt;p&gt;字典查询（Dictionary lookup）&lt;br&gt;
属性或方法查询（Attribute or method lookup）&lt;br&gt;
数字索引查询（Numeric index lookup）&lt;/p&gt;
&lt;p&gt;注意事项：&lt;/p&gt;
&lt;p&gt;如果计算结果的值是可调用的，它将被无参数的调用。 调用的结果将成为模版的值。&lt;/p&gt;
&lt;p&gt;如果使用的变量不存在， 模版系统将插入 string_if_invalid 选项的值， 它被默认设置为&amp;rsquo;&amp;rsquo; (空字符串) 。&lt;/p&gt;
&lt;p&gt;几个例子：&lt;/p&gt;
&lt;p&gt;view中代码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def template_test(request):
    l = [11, 22, 33]
    d = {&amp;quot;name&amp;quot;: &amp;quot;alex&amp;quot;}

    class Person(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age

        def dream(self):
            return &amp;quot;{} is dream...&amp;quot;.format(self.name)

    Alex = Person(name=&amp;quot;Alex&amp;quot;, age=34)
    Egon = Person(name=&amp;quot;Egon&amp;quot;, age=9000)
    Eva_J = Person(name=&amp;quot;Eva_J&amp;quot;, age=18)

    person_list = [Alex, Egon, Eva_J]
    return render(request, &amp;quot;template_test.html&amp;quot;, {&amp;quot;l&amp;quot;: l, &amp;quot;d&amp;quot;: d, &amp;quot;person_list&amp;quot;: person_list})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;模板中支持的写法：&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Django】路由层、视图层</title>
      <link>https://zhong-er.com/posts/django%E8%B7%AF%E7%94%B1%E5%B1%82%E8%A7%86%E5%9B%BE%E5%B1%82/</link>
      <pubDate>Tue, 17 Sep 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/django%E8%B7%AF%E7%94%B1%E5%B1%82%E8%A7%86%E5%9B%BE%E5%B1%82/</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201909169981_9838.jpg&#34;&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.Django orm中表与表之间建关系&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;数据库表与表之间建关系&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;图书管理系统为例，书籍表，作者表，出版社表，作者详情表&lt;/p&gt;
&lt;p&gt;书籍和出版社是一对多 外键字段建在书籍表中&lt;/p&gt;
&lt;p&gt;书籍和作者是多对多 需要第三个表记录多对多关系&lt;/p&gt;
&lt;p&gt;作者和作者详情是一对一 记录在最常用的那张表&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Django orm中&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一对多 ForeignKey(to=&amp;lsquo;Publish&amp;rsquo;)&lt;/p&gt;
&lt;p&gt;一对一 OneToOneField(to=&amp;lsquo;AuthorDetail&amp;rsquo;)&lt;/p&gt;
&lt;p&gt;多对多 ManyToManyField(to=&amp;lsquo;Author&amp;rsquo;)&lt;/p&gt;
&lt;p&gt;注意：前面两个关键字会自动在字段后面加id&lt;/p&gt;
&lt;p&gt;最后一个关键字 并不会产生实际字段 只是告诉django orm自动创建第三张表&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.路由层&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.1 URL配置&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;基本格式【1.0版本】&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from django.conf.urls import url

urlpatterns = [
     url(正则表达式, views视图函数，参数，别名),
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;基本格式【2.0版本】&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from django.urls import path

urlpatterns = [
    path(&#39;articles/2003/&#39;, views.special_case_2003),
    path(&#39;articles/&amp;lt;int:year&amp;gt;/&#39;, views.year_archive),
    path(&#39;articles/&amp;lt;int:year&amp;gt;/&amp;lt;int:month&amp;gt;/&#39;, views.month_archive),
    path(&#39;articles/&amp;lt;int:year&amp;gt;/&amp;lt;int:month&amp;gt;/&amp;lt;slug:slug&amp;gt;/&#39;, views.article_detail),
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;2.0版本已经不能使用正则表达式，只能精准匹配&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.0版本参数说明&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;正则表达式：一个正则表达式字符串&lt;/p&gt;
&lt;p&gt;views视图函数：一个可调用对象，通常为一个视图函数或一个指定视图函数路径的字符串&lt;/p&gt;
&lt;p&gt;参数：可选的要传递给视图函数的默认参数（字典形式）&lt;/p&gt;
&lt;p&gt;别名：一个可选的name参数&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Django版本区别&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;django1.X跟django2.X版本区别&lt;/p&gt;
&lt;p&gt;1.路由层1.X用的是url，而2.X用的是path&lt;/p&gt;
&lt;p&gt;2.路由层2.X中的path第一个参数不再是正则表达式,而是写什么就匹配什么 是精准匹配,&lt;/p&gt;
&lt;p&gt;3.当你使用2.X不习惯的时候,2.X还有一个叫re_path，2.x中的re_path就是你1.X的url&lt;/p&gt;
&lt;p&gt;4.虽然2.X中path不支持正则表达式 但是它提供了五种默认的转换器&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Django】总览</title>
      <link>https://zhong-er.com/posts/django%E6%80%BB%E8%A7%88/</link>
      <pubDate>Mon, 16 Sep 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/django%E6%80%BB%E8%A7%88/</guid>
      <description>&lt;p&gt;&lt;strong&gt;Django简易版&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1. 纯手撸一个简易版的web框架&lt;/p&gt;
&lt;p&gt;1.1 手动处理socket请求&lt;/p&gt;
&lt;p&gt;1.2 手动处理http请求&lt;/p&gt;
&lt;p&gt;1.3 根据用户访问url的不同，响应不同的结果&lt;/p&gt;
&lt;p&gt;2. wsgireg模块(web服务端网关接口)&lt;/p&gt;
&lt;p&gt;2.1 封装socket代码&lt;/p&gt;
&lt;p&gt;2.2 拆分请求发来时的http格式的数据为一个大字典&lt;/p&gt;
&lt;p&gt;2.3 打包数据为响应发回时的http格式的数据&lt;/p&gt;
&lt;p&gt;2.4 启动&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;server = make_server(&#39;127.0.0.1&#39;,8080,run)  # 实时监测，一旦有客户端接入，自动加括号调用run方法
server.server_forever()  # 启动服务端
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;3. 如何给html页面传递数据&lt;/p&gt;
&lt;p&gt;3.1 字符串替换&lt;/p&gt;
&lt;p&gt;3.2 jinja2模块&lt;/p&gt;
&lt;p&gt;1. 模版的渲染(传数据)&lt;/p&gt;
&lt;p&gt;2. 模版语法(极其贴近python语法)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from  jinja2 import Template
# 将文本格式的html数据传入Template
render()

# 模板语法
{{ data }}
{% for user in user_list %}
{% endfor %}

# 模板语法 只有两种情况 
{{}}:变量相关
{%%}:逻辑相关
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;4.对不同的功能拆封成不同的文件&lt;/p&gt;
&lt;p&gt;templates文件夹(专门放html文件)&lt;/p&gt;
&lt;p&gt;urls.py&lt;/p&gt;
&lt;p&gt;views.py&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Django总览版&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Django】框架简介</title>
      <link>https://zhong-er.com/posts/django%E6%A1%86%E6%9E%B6%E7%AE%80%E4%BB%8B/</link>
      <pubDate>Thu, 12 Sep 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/django%E6%A1%86%E6%9E%B6%E7%AE%80%E4%BB%8B/</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201909169981_9838.jpg&#34;&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Web框架本质&lt;/p&gt;
&lt;p&gt;我们可以这样理解：所有的Web应用本质上就是一个socket服务端，而用户的浏览器就是一个socket客户端。 这样我们就可以自己实现Web框架了。&lt;/p&gt;
&lt;p&gt;半成品自定义web框架&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import socket

sk = socket.socket()
sk.bind((&amp;quot;127.0.0.1&amp;quot;, 80))
sk.listen()


while True:
    conn, addr = sk.accept()
    data = conn.recv(8096)
    conn.send(b&amp;quot;OK&amp;quot;)
    conn.close()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以说Web服务本质上都是在这十几行代码基础上扩展出来的。这段代码就是它们的祖宗。&lt;/p&gt;
&lt;p&gt;用户的浏览器一输入网址，会给服务端发送数据，那浏览器会发送什么数据？怎么发？这个谁来定？ 你这个网站是这个规定，他那个网站按照他那个规定，这互联网还能玩么？&lt;/p&gt;
&lt;p&gt;所以，必须有一个统一的规则，让大家发送消息、接收消息的时候有个格式依据，不能随便写。&lt;/p&gt;
&lt;p&gt;这个规则就是HTTP协议，以后浏览器发送请求信息也好，服务器回复响应信息也罢，都要按照这个规则来。&lt;/p&gt;
&lt;p&gt;HTTP协议主要规定了客户端和服务器之间的通信格式，那HTTP协议是怎么规定消息格式的呢？&lt;/p&gt;
&lt;p&gt;让我们首先打印下我们在服务端接收到的消息是什么。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import socket

sk = socket.socket()
sk.bind((&amp;quot;127.0.0.1&amp;quot;, 80))
sk.listen()


while True:
    conn, addr = sk.accept()
    data = conn.recv(8096)
    print(data)  # 将浏览器发来的消息打印出来
    conn.send(b&amp;quot;OK&amp;quot;)
    conn.close()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;b&#39;GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nDNT: 1\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=RKBXh1d3M97iz03Rpbojx1bR6mhHudhyX5PszUxxG3bOEwh1lxFpGOgWN93ZH3zv\r\n\r\n&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后我们再看一下我们访问博客园官网时浏览器收到的响应信息是什么。&lt;/p&gt;</description>
    </item>
    <item>
      <title>【并发编程】IO模型</title>
      <link>https://zhong-er.com/posts/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8Bio%E6%A8%A1%E5%9E%8B/</link>
      <pubDate>Thu, 15 Aug 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8Bio%E6%A8%A1%E5%9E%8B/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;IO模型.png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908156909_500_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;IO模型 &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/2BCYe2Z478&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11359300.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;IO模型介绍&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为了更好地了解IO模型，我们需要事先回顾下：同步、异步、阻塞、非阻塞&lt;/p&gt;
&lt;p&gt;同步（synchronous） IO和异步（asynchronous） IO，阻塞（blocking） IO和非阻塞（non-blocking）IO分别是什么，到底有什么区别？这个问题其实不同的人给出的答案都可能不同，比如wiki，就认为asynchronous IO和non-blocking IO是一个东西。这其实是因为不同的人的知识背景不同，并且在讨论这个问题的时候上下文(context)也不相同。所以，为了更好的回答这个问题，我先限定一下本文的上下文。&lt;/p&gt;
&lt;p&gt;本文讨论的背景是Linux环境下的network IO。本文最重要的参考文献是Richard Stevens的“UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking ”，6.2节“I/O Models ”，Stevens在这节中详细说明了各种IO的特点和区别，如果英文够好的话，推荐直接阅读。Stevens的文风是有名的深入浅出，所以不用担心看不懂。本文中的流程图也是截取自参考文献。&lt;/p&gt;
&lt;p&gt;Stevens在文章中一共比较了五种IO Model：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;blocking IO 阻塞IO&lt;/li&gt;
&lt;li&gt;nonblocking IO 非阻塞IO&lt;/li&gt;
&lt;li&gt;IO multiplexing IO多路复用&lt;/li&gt;
&lt;li&gt;signal driven IO 信号驱动IO&lt;/li&gt;
&lt;li&gt;asynchronous IO 异步IO&lt;br&gt;
由signal driven IO（信号驱动IO）在实际中并不常用，所以主要介绍其余四种IO Model。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;再说一下IO发生时涉及的对象和步骤。对于一个network IO (这里我们以read举例)，它会涉及到两个系统对象，一个是调用这个IO的process (or thread)，另一个就是系统内核(kernel)。当一个read操作发生时，该操作会经历两个阶段：&lt;/p&gt;
&lt;p&gt;#1）等待数据准备 (Waiting for the data to be ready)&lt;/p&gt;
&lt;p&gt;#2）将数据从内核拷贝到进程中(Copying the data from the kernel to the process)&lt;/p&gt;</description>
    </item>
    <item>
      <title>【并发编程】进程池/线程池/协程</title>
      <link>https://zhong-er.com/posts/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E8%BF%9B%E7%A8%8B%E6%B1%A0%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%8D%8F%E7%A8%8B/</link>
      <pubDate>Thu, 15 Aug 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E8%BF%9B%E7%A8%8B%E6%B1%A0%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%8D%8F%E7%A8%8B/</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;img alt=&#34;并发编程(四).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908152948_8824_1.png&#34;&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;并发编程(四) &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/3EDdlPqM78&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11359207.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;进程池与线程池&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;什么是池？在保证计算机硬件安全的情况下最大限度的利用计算机 池其实是降低了程序的运行效率 但是保证了计算机硬件的安全 (硬件的发展跟不上软件的速度)&lt;/p&gt;
&lt;p&gt;p = ThreadPoolExecutor()创建线程池，括号内可以传参数指定线程池内的线程个数，也可以不传，不传默认是当前所在计算机的cpu个数乘5&lt;/p&gt;
&lt;p&gt;p = ProcessPoolExecutor()创建进程池，默认是当前计算机cpu的个数&lt;/p&gt;
&lt;p&gt;池子中创建的进程/线程创建一次就不会再创建了，至始至终用的都是最初的那几个，这样的话节省了反复开辟进程/线程的资源&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;concurrent.futures 模块提供异步执行回调高层接口&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;异步执行可以由 ThreadPoolExecutor 使用线程或由 ProcessPoolExecutor 使用单独的进程来实现。 两者都是实现抽像类 Executor 定义的接口。&lt;/p&gt;
&lt;p&gt;p.submit(fn, *args, **kwargs)朝池子提交任务，异步提交&lt;/p&gt;
&lt;h1 id=&#34;调度可调用对象-fn以-fnargs-kwargs-方式执行并返回-future-对像代表可调用对象的执行&#34;&gt;调度可调用对象 fn，以 fn(*args **kwargs) 方式执行并返回 Future 对像代表可调用对象的执行。&lt;/h1&gt;
&lt;p&gt;p.shutdown(wait=True)关闭池子&lt;/p&gt;
&lt;p&gt;#等待池子中所有的任务执行完毕之后 才会往下运行代码&lt;/p&gt;
&lt;p&gt;ThreadPoolExecutor 是 Executor 的子类，它使用线程池来异步执行调用。&lt;/p&gt;
&lt;p&gt;ProcessPoolExecutor 是 Executor 的子类，它使用进程池来实现异步执行调用。&lt;/p&gt;
&lt;h1 id=&#34;processpoolexecutor-使用-multiprocessing-回避-global-interpreter-lock-但也意味着只可以处理和返回可序列化的对象-main-模块必须可以被工作者子进程导入这意味着-processpoolexecutor-不可以工作在交互式解释器中&#34;&gt;ProcessPoolExecutor 使用 multiprocessing 回避 Global Interpreter Lock 但也意味着只可以处理和返回可序列化的对象。 &lt;strong&gt;main&lt;/strong&gt; 模块必须可以被工作者子进程导入。这意味着 ProcessPoolExecutor 不可以工作在交互式解释器中。&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;异步回调&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;提交任务的方式&lt;/p&gt;
&lt;p&gt;同步：提交任务之后 原地等待任务的返回结果 期间不做任何事&lt;/p&gt;
&lt;p&gt;异步：提交任务之后 不等待任务的返回结果(异步的结果怎么拿？？？) 直接执行下一行代码&lt;/p&gt;
&lt;p&gt;异步回调机制:当异步提交的任务有返回结果之后，会自动触发回调函数的执行&lt;/p&gt;
&lt;p&gt;result()原地等待任务的返回结果&lt;/p&gt;
&lt;p&gt;p.submit(fn,*args, **kwargs).add_done_callback(fn)提交任务的时候 绑定一个回调函数 一旦该任务有结果 立刻执行对于的回调函数&lt;/p&gt;</description>
    </item>
    <item>
      <title>【并发编程】锁/线程队列/信号量/Event事件</title>
      <link>https://zhong-er.com/posts/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E9%94%81%E7%BA%BF%E7%A8%8B%E9%98%9F%E5%88%97%E4%BF%A1%E5%8F%B7%E9%87%8Fevent%E4%BA%8B%E4%BB%B6/</link>
      <pubDate>Wed, 14 Aug 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E9%94%81%E7%BA%BF%E7%A8%8B%E9%98%9F%E5%88%97%E4%BF%A1%E5%8F%B7%E9%87%8Fevent%E4%BA%8B%E4%BB%B6/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;并发编程(三).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908143610_2559_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;并发编程(三) &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/2TRm4OQzz8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11352646.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GIL全局解释器锁&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Cpython解释器：python解释器有很多种，最常见的就是Cpython解释器&lt;/p&gt;
&lt;p&gt;GIL本质也是一把互斥锁&lt;/p&gt;
&lt;p&gt;将并发变成串行牺牲效率保证数据的安全&lt;/p&gt;
&lt;p&gt;用来阻止同一个进程下的多个线程的同时执行&lt;/p&gt;
&lt;p&gt;(同一个进程内多个线程无法实现并行但是可以实现并发)&lt;/p&gt;
&lt;p&gt;GIL的存在是因为CPython解释器的内存管理不是线程安全的&lt;/p&gt;
&lt;p&gt;因为进程内的垃圾回收机制也是一个线程，所以有可能造成其他线程例如赋值时，刚创建值，还没指向变量名就被回收，再赋值直接报错&lt;/p&gt;
&lt;p&gt;python的多线程没法利用多核优势 是不是就是没有用了?&lt;/p&gt;
&lt;p&gt;研究python的多线程是否有用需要分情况讨论&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;四个任务 计算密集型的  10s
单核情况下
    开线程更省资源
多核情况下
    开进程 10s
    开线程 40s
四个任务 IO密集型的  
单核情况下
    开线程更节省资源
多核情况下
    开线程更节省资源
python的多线程到底有没有用
需要看情况而定  并且肯定是有用的
多进程+多线程配合使用
多线程不能使用多核是所有解释型语言的通病
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;GIL与普通互斥锁&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from threading import Thread
import time
n = 100
def task():
    global n
    tmp = n
    # time.sleep(1)
    n = tmp -1
t_list = []
for i in range(100):
    t = Thread(target=task)
    t.start()
    t_list.append(t)
for t in t_list:
    t.join()
print(n)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;死锁与递归锁&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【并发编程】队列/进程间通信/线程</title>
      <link>https://zhong-er.com/posts/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E9%98%9F%E5%88%97%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1%E7%BA%BF%E7%A8%8B/</link>
      <pubDate>Mon, 12 Aug 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E9%98%9F%E5%88%97%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1%E7%BA%BF%E7%A8%8B/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;并发编程(二).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908124424_9438_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;并发编程(二) &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/ZRlhGS9Ua&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11340425.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;队列&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;队列：先进先出&lt;/p&gt;
&lt;p&gt;堆栈：先进后出&lt;/p&gt;
&lt;p&gt;q = Queue(5) 括号内可以传参数：表示的是这个队列的最大存储数&lt;/p&gt;
&lt;p&gt;q.put(1) 括号内可以传参数：表示往队列中添加数据，当对列满了，程序会阻塞，直到有人从队列中取走值&lt;/p&gt;
&lt;p&gt;q.get()：表示向队列取值，当取完后再次获取，程序会阻塞，直到有人往队列存入值&lt;/p&gt;
&lt;p&gt;q.full()：判断对列是否满了&lt;/p&gt;
&lt;p&gt;q.empty()：判断队列中的数据是否取完&lt;/p&gt;
&lt;p&gt;q.get_nowait()：取值，没有值不等待直接报错&lt;/p&gt;
&lt;p&gt;full,get_nowait,empty都不适用与多进程的情况&lt;/p&gt;
&lt;p&gt;其他方法&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;q.qsize() 
    返回队列中目前项目的正确数量。此函数的结果并不可靠，因为在返回结果和在稍后程序中使用结果之间，队列中可能添加或删除了项目。在某些系统上，此方法可能引发NotImplementedError异常。
q.close() 
    关闭队列，防止队列中加入更多数据。调用此方法时，后台线程将继续写入那些已入队列但尚未写入的数据，但将在此方法完成时马上关闭。如果q被垃圾收集，将自动调用此方法。关闭队列不会在队列使用者中生成任何类型的数据结束信号或异常。例如，如果某个使用者正被阻塞在get（）操作上，关闭生产者中的队列不会导致get（）方法返回错误。
q.cancel_join_thread()
    不会再进程退出时自动连接后台线程。这可以防止join_thread()方法阻塞。
q.join_thread() 
    连接队列的后台线程。此方法用于在调用q.close()方法后，等待所有队列项被消耗。默认情况下，此方法由不是q的原始创建者的所有进程调用。调用q.cancel_join_thread()方法可以禁止这种行为。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;进程间的通信IPC机制&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;子进程放数据，主进程获取数据&lt;/p&gt;
&lt;p&gt;两个子进程相互放，取数据&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from multiprocessing import Process,Queue
def producer(q):
    q.put(&#39;hello GF~&#39;)
def consumer(q):
    print(q.get())
if __name__ == &#39;__main__&#39;:
    q = Queue()
    p = Process(target=producer,args=(q,))
    c = Process(target=consumer, args=(q,))
    p.start()
    c.start()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;生产者消费者模型&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;生产者：生产/制造数据的&lt;/p&gt;
&lt;p&gt;消费者：消费/处理数据的&lt;/p&gt;
&lt;p&gt;例子：做包子的，买包子的&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 1.做包子远比买包子的多
# 2.做包子的远比包子的少
# 供需不平衡的问题
from multiprocessing import Process,Queue,JoinableQueue
import random
import time
def producer(name,food,q):
    for i in range(10):
        data = &#39;%s生产了%s%s&#39;%(name,food,i)
        time.sleep(random.random())
        q.put(data)
        print(data)
def consumer(name,q):
    while True:
        data = q.get()
        if data == None:break
        print(&#39;%s吃了%s&#39;%(name,data))
        time.sleep(random.random())
        q.task_done()  # 告诉队列你已经从队列中取出了一个数据 并且处理完毕了
if __name__ == &#39;__main__&#39;:
    q = JoinableQueue()
    p = Process(target=producer,args=(&#39;大厨egon&#39;,&#39;馒头&#39;,q))
    p1 = Process(target=producer,args=(&#39;跟班tank&#39;,&#39;生蚝&#39;,q))
    c = Process(target=consumer,args=(&#39;许兆龙&#39;,q))
    c1 = Process(target=consumer,args=(&#39;吃货jerry&#39;,q))
    p.start()
    p1.start()
    c.daemon = True
    c1.daemon = True
    c.start()
    c1.start()
    p.join()
    p1.join()
    q.join()  # 等到队列中数据全部取出
    # q.put(None)
    # q.put(None)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;线程&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【并发编程】进程</title>
      <link>https://zhong-er.com/posts/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E8%BF%9B%E7%A8%8B/</link>
      <pubDate>Sun, 11 Aug 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E8%BF%9B%E7%A8%8B/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;并发编程(一).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908119816_8792_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;并发编程(一) &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/3SQHwb0bb8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11337291.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;操作系统的作用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1：隐藏丑陋复杂的硬件接口，提供良好的抽象接口&lt;/p&gt;
&lt;p&gt;2：管理、调度进程，并且将多个进程对硬件的竞争变得有序&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;多道技术&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.空间上的复用：多个赓续公用一套计算机硬件&lt;/p&gt;
&lt;p&gt;2.时间上的复用：切换+保存状态&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;1.当一个程序遇到IO操作
操作系统会剥夺该程序的cpu执行权限(提高了cpu的利用率 并且也不影响程序的执行效率)
&amp;gt;2.当一个程序长时间占用cpu
操作系统也会剥夺该程序的cpu执行权限(降低了程序的执行效率)
并发:看起来像同时运行的就可以
并行:真正意义上的同时执行
单核的计算机不能实现并行,但是可以实现并发
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;单道程序工作示例&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;单道程序工作示例.png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908114716_2734_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;多道程序工作示例&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;多道程序工作示例.png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908111904_1209.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;进程&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;程序：一堆代码**&lt;br&gt;
**&lt;/p&gt;
&lt;p&gt;进程：正在运行的程序&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;第一，进程是一个实体。每一个进程都有它自己的地址空间，一般情况下，包括文本区域（text region）、数据区域（data region）和堆栈（stack region）。文本区域存储处理器执行的代码；数据区域存储变量和进程执行期间使用的动态分配的内存；堆栈区域存储着活动过程调用的指令和本地变量。
第二，进程是一个“执行中的程序”。程序是一个没有生命的实体，只有处理器赋予程序生命时（操作系统执行之），它才能成为一个活动的实体，我们称其为进程。[3] 
进程是操作系统中最基本、重要的概念。是多道程序系统出现后，为了刻画系统内部出现的动态情况，描述系统内部各道程序的活动规律引进的一个概念,所有多道程序设计操作系统都建立在进程的基础上。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;进程的特征&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;动态性：进程的实质是程序在多道程序系统中的一次执行过程，进程是动态产生，动态消亡的。
并发性：任何进程都可以同其他进程一起并发执行
独立性：进程是一个能独立运行的基本单位，同时也是系统分配资源和调度的独立单位；
异步性：由于进程间的相互制约，使进程具有执行的间断性，即进程按各自独立的、不可预知的速度向前推进
结构特征：进程由程序、数据和进程控制块三部分组成。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;进程的调度&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1.先来先服务调度算法
先来先服务（FCFS）调度算法是一种最简单的调度算法，该算法既可用于作业调度，也可用于进程调度。FCFS算法比较有利于长作业（进程），而不利于短作业（进程）。由此可知，本算法适合于CPU繁忙型作业，而不利于I/O繁忙型的作业（进程）。
2.短作业优先调度算法
短作业（进程）优先调度算法（SJ/PF）是指对短作业或短进程优先调度的算法，该算法既可用于作业调度，也可用于进程调度。但其对长作业不利；不能保证紧迫性作业（进程）被及时处理；作业的长短只是被估算出来的。
3.时间片轮转法
时间片轮转(Round Robin，RR)法的基本思路是让每个进程在就绪队列中的等待时间与享受服务的时间成比例。在时间片轮转法中，需要将CPU的处理时间分成固定大小的时间片，例如，几十毫秒至几百毫秒。如果一个进程在被调度选中之后用完了系统规定的时间片，但又未完成要求的任务，则它自行释放自己所占有的CPU而排到就绪队列的末尾，等待下一次调度。同时，进程调度程序又去调度当前就绪队列中的第一个进程。 显然，轮转法只能用来调度分配一些可以抢占的资源。这些可以抢占的资源可以随时被剥夺，而且可以将它们再分配给别的进程。CPU是可抢占资源的一种。但打印机等资源是不可抢占的。由于作业调度是对除了CPU之外的所有系统硬件资源的分配，其中包含有不可抢占资源，所以作业调度不使用轮转法。在轮转法中，时间片长度的选取非常重要。首先，时间片长度的选择会直接影响到系统的开销和响应时间。如果时间片长度过短，则调度程序抢占处理机的次数增多。这将使进程上下文切换次数也大大增加，从而加重系统开销。反过来，如果时间片长度选择过长，例如，一个时间片能保证就绪队列中所需执行时间最长的进程能执行完毕，则轮转法变成了先来先服务法。时间片长度的选择是根据系统对响应时间的要求和就绪队列中所允许最大的进程数来确定的。 在轮转法中，加入到就绪队列的进程有3种情况： 一种是分给它的时间片用完，但进程还未完成，回到就绪队列的末尾等待下次调度去继续执行。 另一种情况是分给该进程的时间片并未用完，只是因为请求I/O或由于进程的互斥与同步关系而被阻塞。当阻塞解除之后再回到就绪队列。 第三种情况就是新创建进程进入就绪队列。 如果对这些进程区别对待，给予不同的优先级和时间片从直观上看，可以进一步改善系统服务质量和效率。例如，我们可把就绪队列按照进程到达就绪队列的类型和进程被阻塞时的阻塞原因分成不同的就绪队列，每个队列按FCFS原则排列，各队列之间的进程享有不同的优先级，但同一队列内优先级相同。这样，当一个进程在执行完它的时间片之后，或从睡眠中被唤醒以及被创建之后，将进入不同的就绪队列。
4.多级反馈队列
前面介绍的各种用作进程调度的算法都有一定的局限性。如短进程优先的调度算法，仅照顾了短进程而忽略了长进程，而且如果并未指明进程的长度，则短进程优先和基于进程长度的抢占式调度算法都将无法使用。而多级反馈队列调度算法则不必事先知道各种进程所需的执行时间，而且还可以满足各种类型进程的需要，因而它是目前被公认的一种较好的进程调度算法。在采用多级反馈队列调度算法的系统中，调度算法的实施过程如下所述。(1) 应设置多个就绪队列，并为各个队列赋予不同的优先级。第一个队列的优先级最高，第二个队列次之，其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片的大小也各不相同，在优先权愈高的队列中，为每个进程所规定的执行时间片就愈小。例如，第二个队列的时间片要比第一个队列的时间片长一倍，……，第i+1个队列的时间片要比第i个队列的时间片长一倍。(2) 当一个新进程进入内存后，首先将它放入第一队列的末尾，按FCFS原则排队等待调度。当轮到该进程执行时，如它能在该时间片内完成，便可准备撤离系统；如果它在一个时间片结束时尚未完成，调度程序便将该进程转入第二队列的末尾，再同样地按FCFS原则等待调度执行；如果它在第二队列中运行一个时间片后仍未完成，再依次将它放入第三队列，……，如此下去，当一个长作业(进程)从第一队列依次降到第n队列后，在第n 队列便采取按时间片轮转的方式运行。(3) 仅当第一队列空闲时，调度程序才调度第二队列中的进程运行；仅当第1～(i-1)队列均空时，才会调度第i队列中的进程运行。如果处理机正在第i队列中为某进程服务时，又有新进程进入优先权较高的队列(第1～(i-1)中的任何一个队列)，则此时新进程将抢占正在运行进程的处理机，即由调度程序把正在运行的进程放回到第i队列的末尾，把处理机分配给新到的高优先权进程。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&#34;时间片转轮发+多级反馈队列.jpg&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908118541_248.jpg-zhonger.com&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;进程的并发与并行&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;并行： 并行是指两者同时执行（资源够用，比如三个线程，四核的CPU ）
并发：并发是指资源有限的情况下，两者交替轮流使用资源
区别
并行是从微观上，也就是在一个精确的时间片刻，有不同的程序在执行，这就要求必须有多个处理器
并发是从宏观上，在一个时间段上可以看出是同时执行的，比如一个服务器同时处理多个session
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;同步异步阻塞非阻塞&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】异常处理</title>
      <link>https://zhong-er.com/posts/python%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86/</link>
      <pubDate>Thu, 08 Aug 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86/</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;img alt=&#34;Python异常处理.png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908112295_3450_1.png&#34;&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python异常处理 &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/3HxHgXnqf8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11322367.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;什么是异常处理？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;程序在运行过程中出现了不可预知的错误&lt;/p&gt;
&lt;p&gt;并且该错误没有对应的处理机制，那么就会以异常的形式表现出来&lt;/p&gt;
&lt;p&gt;造成的影响就是整个程序无法正常运行&lt;/p&gt;
&lt;p&gt;异常的结构&lt;/p&gt;
&lt;p&gt;1.异常的类型：NAMEERROR&lt;/p&gt;
&lt;p&gt;2.异常的信息：name &amp;lsquo;abc&amp;rsquo; is not defined&lt;/p&gt;
&lt;p&gt;3.异常的位置：Traceback (most recent call last): File &amp;ldquo;路径&amp;rdquo;, line 1, in &lt;module&gt; abc&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;异常的种类：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.语法错误&lt;br&gt;
是你程序立刻就能解决的，这种错误是不能被容忍的，语法上的错误，发现之后应该立刻解决&lt;/p&gt;
&lt;p&gt;2.逻辑错误&lt;br&gt;
这种错误是可以被容忍的，因为一眼看不出来，针对逻辑上的错误，可以采用异常处理机制进行捕获&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;常见的错误类型&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;NameError 名字错误&lt;/p&gt;
&lt;p&gt;SyntaxError 语法错误&lt;/p&gt;
&lt;p&gt;KeyError 健不存在&lt;/p&gt;
&lt;p&gt;valueError 值错误&lt;/p&gt;
&lt;p&gt;IndexError 索引错误&lt;/p&gt;
&lt;p&gt;TypeError 类型错误&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;异常处理&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在你认为可能出现bug的代码块上方try一下&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;try:
	可能出错的代码
except 出错的类型 as e:  # 将报错信息赋值给变量e
	出错之后的处理机制
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意try内部的代码块越少越好&lt;/p&gt;
&lt;p&gt;try后可跟多种except异常类型的捕获，但是不会连续连续捕获，因为有一个错误发生之后，会立刻停止代码的运行，执行该类型错误的except语句&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;try:
    name
    l = [1,2,3]
    l[111]
    d = {&#39;name&#39;:&#39;jason&#39;}
    d[&#39;password&#39;]
except NameError:
    print(&#39;NameError&#39;)
except IndexError:
    print(&#39;indexerror&#39;)
except KeyError:
    print(&#39;keyerror&#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Exception 所有异常的基类，所有异常类型都被捕获&lt;/p&gt;</description>
    </item>
    <item>
      <title>【网络编程】Socket</title>
      <link>https://zhong-er.com/posts/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bsocket/</link>
      <pubDate>Thu, 08 Aug 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bsocket/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;网络编程(三).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908085255_559_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;网络编程(三) &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/FpZaknXLa&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11322341.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;基于TCP协议使用socket分发大文件&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;案例：电影上传&lt;/p&gt;
&lt;p&gt;思路：客户端端循环一行一行读文件并一行一行传输，服务端循环接收并写入文件&lt;/p&gt;
&lt;p&gt;客户端代码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import socket,json,os,struct
client = cocket.socket()
client.connet((&#39;127.0.0.1&#39;,8080))
while True:
    # 获取电影类表，循环展示
    MOVIE_DIR = r&#39;D:\路径\视频&#39;
    movie_list = os.listdir(MOVIE_DIR)
    for i,movie in enumerate(movie_list,1):
        print(i,movie)
    # 用户选择
    choice = input(&#39;please choice movie to upload&amp;gt;&amp;gt;&amp;gt;:&#39;)
    # 判断是否是数字
    if choice.isdigit():
        # 将字符串转为int
        choice = in(choice) - 1
        # 判断用户选择在不在列表范围内
        if choice in range(0,len(movie_list))
           # 获取用户想上传的文件路径
            path = movie_list[choice]
           # 拼接文件的绝对路径
           file_path = os.path.join(MOVIE_DIR,path)
           # 获取文件的大小
           file_size = os.path.getsize(file_path)
           # 定义一个字典
           res_d = {
                      &#39;file_name&#39;:&#39;性感荷官在线发牌.,mp4&#39;,
                      &#39;file_size&#39;:file_size,
                      &#39;msg&#39;:&#39;注意身体，多喝营养快线&#39;
           }
           # 序列话字典
           json_d = json.dunps(res_d)
           json_bytes = json_d.encode(&#39;utf-8&#39;)
           # 1.先制作字典格式的报头
           header = struct.pack(&#39;i&#39;,len(json_bytes))
           # 2.发送字典的报头
           client.send(header)
           # 3.再发字典
           client.send(json_bytes)
           # 4.再发文件数据(打开文件循环发送)
           with open(file_path,r&#39;b&#39;) as f:
               for line in f:
                   client.send(line)
        else:
           print(&#39;not in rang&#39;)
    else:
        print(&#39;must be a number&#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;服务端代码&lt;/p&gt;</description>
    </item>
    <item>
      <title>【网络编程】TCP协议与粘包问题</title>
      <link>https://zhong-er.com/posts/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Btcp%E5%8D%8F%E8%AE%AE%E4%B8%8E%E7%B2%98%E5%8C%85%E9%97%AE%E9%A2%98/</link>
      <pubDate>Wed, 07 Aug 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Btcp%E5%8D%8F%E8%AE%AE%E4%B8%8E%E7%B2%98%E5%8C%85%E9%97%AE%E9%A2%98/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;网络编程(二).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908079748_6105_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;网络编程(二) &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/M0ZxVWd7a&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11317624.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;基于TCP协议的Socket套接字&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;server端&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import socket
sk = socket.socket()
sk.bind((&#39;127.0.0.1&#39;,8898))  # 把地址绑定到套接字
sk.listen()          # 监听链接
conn,addr = sk.accept() # 接受客户端链接
ret = conn.recv(1024)  # 接收客户端信息
print(ret)       # 打印客户端信息
conn.send(b&#39;hi&#39;)        # 向客户端发送信息
conn.close()       # 关闭客户端套接字
sk.close()        # 关闭服务器套接字(可选)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;client端&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import socket
sk = socket.socket()           # 创建客户套接字
sk.connect((&#39;127.0.0.1&#39;,8898))    # 尝试连接服务器
sk.send(b&#39;hello!&#39;)
ret = sk.recv(1024)         # 对话(发送/接收)
print(ret)
sk.close()            # 关闭客户套接字
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;127.0.0.1本机回还地址：只能自己识别自己 其他人无法访问&lt;/p&gt;
&lt;p&gt;send与recv对应，不要出现两边都是相同的情况&lt;/p&gt;
&lt;p&gt;recv是跟内存要数据，至于数据的来源 你无需考虑&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TCP特点&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;会将数据量比较小的并且时间间隔比较短的数据一次性打包发送给对方&lt;/p&gt;
&lt;p&gt;TCP是基于链接的，必须先启动服务端，然后再启动客户端去连接服务端&lt;/p&gt;</description>
    </item>
    <item>
      <title>【网络编程】OSI七层协议/TCP协议</title>
      <link>https://zhong-er.com/posts/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E5%8D%8F%E8%AE%AEtcp%E5%8D%8F%E8%AE%AE/</link>
      <pubDate>Tue, 06 Aug 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Bosi%E4%B8%83%E5%B1%82%E5%8D%8F%E8%AE%AEtcp%E5%8D%8F%E8%AE%AE/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;网络编程.png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908068133_5580_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;网络编程(一) &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/2o2v35H6G8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11312188.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;软件开发架构&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;C/S架构(clinet/server)：客户端/服务端&lt;/p&gt;
&lt;p&gt;B/S架构(browser/server)：浏览器/服务器&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;网络编程发展史&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;任何先进的技术最早都源于军事&lt;/p&gt;
&lt;p&gt;要想实现远程通信第一个需要具备的条件是：物理连接介质&lt;/p&gt;
&lt;p&gt;计算机之间要想实现远程通信除了有物理连接介质还需要一套公共标准/协议、&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OSI七层协议&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;应用层&lt;/strong&gt;&lt;br&gt;
HTTP协议FTP协议&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;表示层&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;会话层&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;传输层&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;TCP\UDP都是基于端口(port)工作的协议
计算机与计算机之间其实是计算机上的应用程序与应用程序之间的通信
端口:用来唯一标识一台计算机上的某个应用程序
端口号的范围:0~65535
注意:0~1024这些都是操作系统默认使用的端口号
建议:使用8000之后的端口
MySQL默认端口:3306
Redis默认端口:6379
django默认端口:8000
flask默认端口:5000	

端口号是动态分配的 第一次起qq分配到的是8989将qq关闭再次启动端口号可能就变了

总结
ip地址:用来唯一标识接入互联网的一台计算机
port端口:用来唯一标识一台计算机上的某个应用程序
ip+port:唯一标识接入互联网一台计算机上的某个应用程序
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;网络层&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IP协议规定了只要是接入互联网的计算机都必须有一个IP地址
ip地址特点:点分十进制
ip地址最小:0.0.0.0
ip地址最大:255.255.255.255
ip地址目前有两个版本:IPV4  IPV6(由于IPV4已经不够表示目前存在的计算机了 所以推出了IPV6版本)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;数据链路层&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1.规定的电信号的分组方式
2.规定了任何一台接入互联网的计算机都必须有一块网卡
每一块网卡上面都刻有世界上独一无二的编号
12位16进制数：前6位是厂商编号，后6位是流水线编号	
我们管这12数叫mac地址
ps:以上两点合称为&amp;quot;以太网协议&amp;quot;
交换机：基于以太网协议通信，不能跨局域网通信。
以太网协议通信的特点：通信基本靠吼！
                缺点：广播风暴
互联网是有N多个局域网彼此之间连接而成的。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;物理连接层&lt;/strong&gt;&lt;br&gt;
基于电信号传输010101001010二进制数据&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TCP协议(详见&lt;/strong&gt;&lt;a href=&#34;%7B#ZC_BLOG_HOST#%7Dpost/56.html&#34; title=&#34;TCP协议三次握手四次挥手&#34;&gt;&lt;strong&gt;《TCP协议三次握手四次挥手》&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;流式协议,可靠协议&lt;/p&gt;
&lt;p&gt;基于TCP协议通信 必先建立双向通道&lt;/p&gt;
&lt;p&gt;TCP协议传输数据可靠的原因在于它有反馈机制，发送消息之后对方必须回复确认收到消息才会将数据从内存中清空，否则在限定的时间时间内会每隔一段时间发送一次，如果超过限定时间还未收到，就会把对方计算机列为宕机或其他故障，停止向此计算机发送消息&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;三次握手&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;所谓三次握手(Three-way Handshake)，是指建立一个 TCP 连接时，需要客户端和服务器总共发送3个包。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;第一次客户端发送SYN包给服务端，客户端发送完毕进入SYN_SEND状态，
第二次服务端收到第一次客户端发送的SYN包后发回ACK确认包并同时也发送一个SYN包到客户端，服务端发送完毕进入SYN_RECV状态，
第三次客户端接收到服务端发送的ACK+SYN包后向服务端发回ACK确认包，发送完毕进入Established状态。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;四次挥手&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【网络编程】TCP协议的三次握手四次挥手-详解</title>
      <link>https://zhong-er.com/posts/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Btcp%E5%8D%8F%E8%AE%AE%E7%9A%84%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B%E5%9B%9B%E6%AC%A1%E6%8C%A5%E6%89%8B-%E8%AF%A6%E8%A7%A3/</link>
      <pubDate>Tue, 06 Aug 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8Btcp%E5%8D%8F%E8%AE%AE%E7%9A%84%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B%E5%9B%9B%E6%AC%A1%E6%8C%A5%E6%89%8B-%E8%AF%A6%E8%A7%A3/</guid>
      <description>&lt;h2 id=&#34;tcp-的特性&#34;&gt;TCP 的特性&lt;/h2&gt;
&lt;p&gt;TCP 提供一种面向连接的、可靠的字节流服务&lt;/p&gt;
&lt;p&gt;在一个 TCP 连接中，仅有两方进行彼此通信。广播和多播不能用于 TCP&lt;/p&gt;
&lt;p&gt;TCP 使用校验和，确认和重传机制来保证可靠传输&lt;/p&gt;
&lt;p&gt;TCP 给数据分节进行排序，并使用累积确认保证数据的顺序不变和非重复&lt;/p&gt;
&lt;p&gt;TCP 使用滑动窗口机制来实现流量控制，通过动态改变窗口的大小进行拥塞控制&lt;/p&gt;
&lt;p&gt;注意：TCP 并不能保证数据一定会被对方接收到，因为这是不可能的。TCP 能够做到的是，如果有可能，就把数据递送到接收方，否则就（通过放弃重传并且中断连接这一手段）通知用户。因此准确说 TCP 也不是 100% 可靠的协议，它所能提供的是数据的可靠递送或故障的可靠通知。&lt;/p&gt;
&lt;h2 id=&#34;三次握手与四次挥手&#34;&gt;三次握手与四次挥手&lt;/h2&gt;
&lt;p&gt;所谓三次握手(Three-way Handshake)，是指建立一个 TCP 连接时，需要客户端和服务器总共发送3个包。&lt;/p&gt;
&lt;p&gt;三次握手的目的是连接服务器指定端口，建立 TCP 连接，并同步连接双方的序列号和确认号，交换 TCP 窗口大小信息。在 socket 编程中，客户端执行 &lt;code&gt;connect()&lt;/code&gt; 时。将触发三次握手。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一次握手(SYN=1, seq=x):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;客户端发送一个 TCP 的 SYN 标志位置1的包，指明客户端打算连接的服务器的端口，以及初始序号 X,保存在包头的序列号(Sequence Number)字段里。&lt;/p&gt;
&lt;p&gt;发送完毕后，客户端进入 &lt;code&gt;SYN_SEND&lt;/code&gt; 状态。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;服务器发回确认包(ACK)应答。即 SYN 标志位和 ACK 标志位均为1。服务器端选择自己 ISN 序列号，放到 Seq 域里，同时将确认序号(Acknowledgement Number)设置为客户的 ISN 加1，即X+1。 发送完毕后，服务器端进入 &lt;code&gt;SYN_RCVD&lt;/code&gt; 状态。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第三次握手(ACK=1，ACKnum=y+1)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;客户端再次发送确认包(ACK)，SYN 标志位为0，ACK 标志位为1，并且把服务器发来 ACK 的序号字段+1，放在确定字段中发送给对方，并且在数据段放写ISN的+1&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】反射/元类</title>
      <link>https://zhong-er.com/posts/python%E5%8F%8D%E5%B0%84%E5%85%83%E7%B1%BB/</link>
      <pubDate>Tue, 30 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E5%8F%8D%E5%B0%84%E5%85%83%E7%B1%BB/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第21课(反射_元类).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907306609_2135_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python反射/元类) &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/3nvhkZgcw8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11271212.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;反射reflect&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;什么是反射, 其实是反省,自省的意思&lt;/p&gt;
&lt;p&gt;反射指的是一个对象应该具备,可以检测,修改,增加自身属性的能力&lt;/p&gt;
&lt;p&gt;反射就是通过字符串操作属性&lt;/p&gt;
&lt;p&gt;涉及的四个函数,这四个函数就是普通的内置函数 没有双下划綫,与print等等没有区别&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hasattr  getattr setattr delattr 

p = Person(&amp;quot;jack&amp;quot;,18,&amp;quot;man&amp;quot;)

# if hasattr(p,&amp;quot;name&amp;quot;): # 1.判断某个对象是否存在某个属性
#     print(getattr(p,&amp;quot;names&amp;quot;,None)) # 2.从对象中取出属性,第三个值位默认值 当属性不存在是返回默认值

# 3.为对象添加新的属性
setattr(p,&amp;quot;id&amp;quot;,&amp;quot;123&amp;quot;)
print(p.id)

# 4.从对象中删除属性
delattr(p,&amp;quot;id&amp;quot;)
print(p.id)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用场景:反射其实就是对属性的增删改查,但是如果直接使用内置的dict来操作,语法繁琐,不好理解&lt;/p&gt;
&lt;p&gt;另外一个最主要的问题是,如果对象不是我自己写的是另一方提供的,我就必须判断这个对象是否满足的要求,也就是是否我需要的属性和方法&lt;/p&gt;
&lt;p&gt;框架代码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;
反射被称为框架的基石,为什么
因为框架的设计者,不可能提前知道你的对象到底是怎么设计的
所以你提供给框架的对象 必须通过判断验证之后才能正常使用
判断验证就是反射要做的事情,
当然通过__dict__也是可以实现的, 其实这些方法也就是对__dict__的操作进行了封装
需求:要实现一个用于处理用户的终端指令的小框架
框架就是已经实现了最基础的构架,就是所有项目都一样的部分
&amp;quot;&amp;quot;&amp;quot;

import plugins

# 框架已经实现的部分
def run(plugin):
    while True:
        cmd = input(&amp;quot;请输入指令:&amp;quot;)
        if cmd == &amp;quot;exit&amp;quot;:
            break
        # 因为无法确定框架使用者是否传入正确的对象所以需要使用反射来检测
        # 判断对象是否具备处理这个指令的方法
        if hasattr(plugin,cmd):
            # 取出对应方法方法
            func = getattr(plugin,cmd)
            func() # 执行方法处理指令
        else:
            print(&amp;quot;该指令不受支持...&amp;quot;)
    print(&amp;quot;see you la la!&amp;quot;)


# 创建一个插件对象 调用框架来使用它
# wincmd = plugins.WinCMD()
# 框架之外的部分就有自定义对象来完成
linux = plugins.LinuxCMD()
run(linux)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;插件部分&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】多态</title>
      <link>https://zhong-er.com/posts/python%E5%A4%9A%E6%80%81/</link>
      <pubDate>Mon, 29 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E5%A4%9A%E6%80%81/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第20课(多态).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907295353_7862_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python多态 &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/2Z5T8az_x8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11264086.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;********&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;多态&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;概念&lt;/strong&gt; ：一种事物具备多种 不同的形态&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;例如&lt;/strong&gt; ：水“固态”、“液态”、“气态”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;官方解释&lt;/strong&gt; ：多个不同类的对象可以响应同一个方法，产生不同的结果&lt;/p&gt;
&lt;p&gt;首先强调多态不是一种特殊的语法，而是一种状态、特性(即多个不同对象可以响应同一个方法，产生不同结果)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;好处&lt;/strong&gt; ：对于使用者而言，大大的降低了使用难度&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;实现多态&lt;/strong&gt; ：接口、抽象类、鸭子类型都可以写出具备多态的代码，最简单的就是鸭子类型&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;案例&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;
要管理 鸡 鸭 鹅
如何能够最方便的 管理,就是我说同一句话,他们都能理解
既它们拥有相同的方法

&amp;quot;&amp;quot;&amp;quot;
class JI:
    def bark(self):
        print(&amp;quot;哥哥哥&amp;quot;)

    def spawn(self):
        print(&amp;quot;下鸡蛋..&amp;quot;)

class Duck:
    def bark(self):
        print(&amp;quot;嘎嘎嘎&amp;quot;)

    def spawn(self):
        print(&amp;quot;下鸭蛋&amp;quot;)

class E:
    def bark(self):
        print(&amp;quot;饿饿饿....&amp;quot;)

    def spawn(self):
        print(&amp;quot;下鹅蛋..&amp;quot;)

j = JI()
y = Duck()
e = E()

def mange(obj):
    obj.spawn()


mange(j)
mange(y)
mange(e)


# python中到处都有多态  
a = 10
b = &amp;quot;10&amp;quot;
c = [10]

print(type(a))
print(type(b))
print(type(c))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;isinstance&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】封装</title>
      <link>https://zhong-er.com/posts/python%E5%B0%81%E8%A3%85/</link>
      <pubDate>Sat, 27 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E5%B0%81%E8%A3%85/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第19课(封装).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907279602_9365_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python封装 &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/3bGhBW7908&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11257242.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;封装&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;什么是封装？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;就是将复杂的丑陋的,隐私的细节隐藏到内部,对外提供简单的使用接口&lt;/p&gt;
&lt;p&gt;对外隐藏内部实现细节,并提供访问的接口&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;什么时候应该封装？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当有一些数据不希望外界可以直接修改时&lt;/p&gt;
&lt;p&gt;当有一些函数不希望给外界使用时&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么需要封装 ？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.为了保证 关键数据的安全性&lt;/p&gt;
&lt;p&gt;2.对外部隐藏实现细节,隔离复杂度&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;语法&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Person:
    def __init__(self,id_number,name,age)
    
	self.__id_number = id_number
        self.name = name
        self.age = age
   
p = Person(&amp;quot;1111111111111&amp;quot;,&amp;quot;jack&amp;quot;,29)
p.id_number = &amp;quot;222&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;被封装的内容的特点:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.外界不能直接访问&lt;/p&gt;
&lt;p&gt;2.内部依然可以使用&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;权限&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;学习了封装后就可以控制属性的权限&lt;/p&gt;
&lt;p&gt;在python只要两种权限&lt;/p&gt;
&lt;p&gt;1.公开的.默认就是公开的&lt;/p&gt;
&lt;p&gt;2.私有的,只能由当前类自己使用&lt;/p&gt;
&lt;p&gt;在外界访问私有的内容&lt;/p&gt;
&lt;p&gt;属性虽然被封装了,但是还是需要使用的,在外界如何访问&lt;/p&gt;
&lt;p&gt;通过定义方法类完成对私有属性的修改和访问&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;
这是一个下载器类,需要提供一个缓存大小这样的属性
缓存大小不能超过内存限制
&amp;quot;&amp;quot;&amp;quot;
class Downloader:
    def __init__(self,filename,url,buffer_size):
        self.filename = filename
        self.url = url
        self.__buffer_size= buffer_size
    def start_download(self):
        if self.__buffer_size &amp;lt;= 1024*1024:
            print(&amp;quot;开始下载....&amp;quot;)
            print(&amp;quot;当前缓冲器大小&amp;quot;,self.__buffer_size)
        else:
            print(&amp;quot;内存炸了! &amp;quot;)
    def set_buffer_size(self,size):
        #可以在方法中添加额外的逻辑
        if not type(size) == int:
            print(&amp;quot;大哥 缓冲器必须是整型&amp;quot;)
        else:
            print(&amp;quot;缓冲区大小修改成功!&amp;quot;)
            self.__buffer_size = size
    def get_buffer_size(self):
        return self.__buffer_size
d = Downloader(&amp;quot;葫芦娃&amp;quot;,&amp;quot;http://www.baicu.com&amp;quot;,1024*1024)
# 通过函数取修改内部封装的属性
d.set_buffer_size(1024*512)
# 通过函数访问内部封装的属性
print(d.get_buffer_size())
d.start_download()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样一来我们可以在外界修改这个关键数据时,做一些限制&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】继承</title>
      <link>https://zhong-er.com/posts/python%E7%BB%A7%E6%89%BF/</link>
      <pubDate>Thu, 25 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E7%BB%A7%E6%89%BF/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第十八课(继承).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907256978_8464_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python继承 ****&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/1E2IpX7lH8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;************************&lt;/a&gt;&lt;strong&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11247379.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;********&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;什么是继承？&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;继承是一种关系,描述两个对象之间,什么是什么的关系
例如麦兜,佩奇,猪刚鬣 都是猪啊,
在程序中,继承描述的是类和类之间的关系  
例如a继承了b, a就能直接使用b已经存在的方法和属性
a称之为子类,b称之为父类,也称之为基类
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;为什么要使用继承&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;继承的一方可以直接使用被继承一方已经有的东西
其目的是为了重用已经有的代码,提高重用性
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;如何使用继承&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;语法&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class 类名称(父类的名称):
    类的内容 
    
#在python中 一个子类可以同时继承多个父类
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;抽象&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;不具体,不清晰,很模糊,看不懂  
将多个子类中相同的部分,进行抽取,形成一个新的类,这个过程也称之为抽象的过程
正确的使用继承:
	1.先抽象在继承
	2.继承一个已经现存的类,扩展或是修改原始的功能
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;属性的查找顺序&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class A:
    text = &amp;quot;haha&amp;quot;

class B(A):
    text = &amp;quot;heihei&amp;quot;
    pass

b = B()
b.text = &amp;quot;xixi&amp;quot;

print(b.text)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对象自己的 - &amp;gt; 所在类中 -&amp;gt; 找父类 - &amp;gt;父类的父类 -&amp;gt;Object&lt;/p&gt;
&lt;p&gt;派生&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;当一个子类中出现了与父类中不同的内容时,这个子类就称之为派生类
通常子类都会写一些新的代码,不可能和父类完全一样 , 既通常都是派生类,
所以派生类指的就是子类
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;覆盖&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】面向对象</title>
      <link>https://zhong-er.com/posts/python%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/</link>
      <pubDate>Wed, 24 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第十七课(面向对象基础).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907245717_4819_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python面向对象 &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/2IXliWSXW8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11239449.html&#34; title=&#34;博客园&#34;&gt;&lt;/a&gt;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11239449.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;面向对象编程思想OOP&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;什么是面向对象&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;[os-copy]&lt;/p&gt;
&lt;p&gt;面向对象是一种编程思想，是前辈们总结出的经验，指导程序员如何编写出更好的程序，核心是对象，程序就是一系列对象的集合，程序员负责调度控制这些对象来交互着完成任务&lt;/p&gt;
&lt;p&gt;案例1 把大象装进冰箱？&lt;br&gt;
面向过程:&lt;br&gt;
1.打开冰箱&lt;br&gt;
2.装入大象&lt;br&gt;
3.关闭冰箱&lt;br&gt;
面向对象:&lt;br&gt;
找个具备装大象的技能的对象&lt;/p&gt;
&lt;p&gt;在面向对象中程序员的角度发生改变，从具体的操作者变成了指挥者&lt;br&gt;
强调：对象不是凭空产生的，需要我们自己设计&lt;/p&gt;
&lt;p&gt;案例2 西天取经&lt;br&gt;
如来有一堆破书要传出去,他没有自己干,&lt;br&gt;
而是找了五个对象帮他去干, 如来只要负责控制调度的对象即可,&lt;/p&gt;
&lt;p&gt;如果某个对象发生变化,也不会影响其他的对象 , 扩展性&lt;/p&gt;
&lt;p&gt;案例3 曹操吟诗&lt;br&gt;
喝酒吃肉,人生真爽&lt;br&gt;
喝酒吃肉,人生几何&lt;br&gt;
对酒当歌,人生几何&lt;/p&gt;
&lt;p&gt;[/os-copy]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;面向对象三大优点&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;[os-copy]&lt;/p&gt;
&lt;p&gt;1.扩展性&lt;/p&gt;
&lt;p&gt;2.灵活性&lt;/p&gt;
&lt;p&gt;3.重用性&lt;/p&gt;
&lt;p&gt;[/os-copy]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;[os-copy]&lt;/p&gt;
&lt;p&gt;1.程序的复杂度提高了&lt;/p&gt;
&lt;p&gt;2.无法准确预知结果&lt;/p&gt;
&lt;p&gt;[/os-copy]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;使用场景：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;对扩展性要求较高，通常是直接面向用户的，例如：QQ，微信&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;面向过程编程思想&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;[os-copy]&lt;/p&gt;
&lt;p&gt;关注的核心是过程,过程是就是一步一步的执行步骤,既先干啥在干啥&lt;/p&gt;
&lt;p&gt;优点:逻辑清晰 , 复杂问题简单化,流程化&lt;/p&gt;
&lt;p&gt;缺点: 扩展性差,可维护性差&lt;/p&gt;
&lt;p&gt;使用场景:对扩展性要求较低的程序例如:系统内核,git,计算器&lt;/p&gt;
&lt;p&gt;记住:不是所有程序都要面向对象,得分析具体需求&lt;/p&gt;
&lt;p&gt;[/os-copy]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;类和对象&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;类&lt;/strong&gt; ：即类型，类别，是一种抽象概念，是一系列具备相同特征和相同行的对象的集合&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;对象&lt;/strong&gt; ：就是具体存在的某个事物，具备自己的特征和行为，对象就是特征和技能的结合体&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;类和对象的关系&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;[os-copy]&lt;/p&gt;
&lt;p&gt;类包含一系列对象，对象属于某个类&lt;/p&gt;
&lt;p&gt;在生活中是先有对象再有类，而在程序中是先有类才能有对象,我们必须先告诉计算机这类的对象有什么特征有什么行为&lt;/p&gt;
&lt;p&gt;总结出一个结论:在使用面向对象编程时,第一步就是思考需要什么样的对象,对象具备什么样的特征和行为,从而根据 这些信息总结出需要的类型&lt;/p&gt;
&lt;p&gt;[/os-copy]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;创建类和对象&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;定义类的语法&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】深浅拷贝/hashlib/logging/openpyxl模块</title>
      <link>https://zhong-er.com/posts/python%E6%B7%B1%E6%B5%85%E6%8B%B7%E8%B4%9Dhashlibloggingopenpyxl%E6%A8%A1%E5%9D%97/</link>
      <pubDate>Fri, 19 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E6%B7%B1%E6%B5%85%E6%8B%B7%E8%B4%9Dhashlibloggingopenpyxl%E6%A8%A1%E5%9D%97/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第十六课(模块3).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907194511_4004_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;深浅拷贝/hashlib/logging/openpyxl模块 &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/1XBfSvM5X8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;博客园&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;模块与包&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;模块&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;
三种来源
    1.内置的
    2.第三方的
    3.自定义的
四种表示形式
    1.py文件(******)
    2.共享库
    3.文件夹(一系列模块的结合体)(******)
    4.C++编译的连接到python内置的
&amp;quot;&amp;quot;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;导入模块&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;
先产生一个执行文件的名称空间
    1.创建模块文件的名称空间
    2.执行模块文件中的代码 将产生的名字放入模块的名称空间中
    3.在执行文件中拿到一个指向模块名称空间的名字
&amp;quot;&amp;quot;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;什么是包&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;
什么是包?
    它是一系列模块文件的结合体,表示形式就是一个文件夹
    该文件夹内部通常会有一个__init__.py文件
    包的本质还是一个模块
&amp;quot;&amp;quot;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;导入包&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;先产生一个执行文件的名称空间
    1.创建包下面的__init__.py文件的名称空间
    2.执行包下面的__init__.py文件中的代码 将产生的名字放入包下面的__init__.py文件名称空间中
    3.在执行文件中拿到一个指向包下面的__init__.py文件名称空间的名字
在导入语句中 .号的左边肯定是一个包(文件夹)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当你作为包的设计者来说&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1.当模块的功能特别多的情况下 应该分文件管理
2.每个模块之间为了避免后期模块改名的问题 你可以使用相对导入(包里面的文件都应该是被导入的模块)
# 研究模块与包 还可以站另外两个角度分析不同的问题
# 1.模块的开发者
# 2.模块的使用者
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;研究模块与包还可以站另外两个角度分析不同的问题&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1.站在包的开发者
如果使用绝对路径来管理的自己的模块 那么它只需要永远以包的路径为基准依次导入模块
2.站在包的使用者
你必须得将包所在的那个文件夹路径添加到system
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python2如果要导入包 包下面必须要有__init__.py文件
python3如果要导入包 包下面没有__init__.py文件也不会报错
当你在删程序不必要的文件的时候 千万不要随意删除__init__.py文件
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;相对导入与绝对导入&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】时间/序列化/sys/os模块</title>
      <link>https://zhong-er.com/posts/python%E6%97%B6%E9%97%B4%E5%BA%8F%E5%88%97%E5%8C%96sysos%E6%A8%A1%E5%9D%97/</link>
      <pubDate>Thu, 18 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E6%97%B6%E9%97%B4%E5%BA%8F%E5%88%97%E5%8C%96sysos%E6%A8%A1%E5%9D%97/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第十五课(模块2).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907191143_207_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python****时间/序列化/sys/os模块 &amp;raquo;&amp;gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/24AoWYUXS8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11210464.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****************&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&#34;collections模块&#34;&gt;collections模块&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;collections模块在内置的数据类型，比如：int、str、list、dict等基础之上额外提供了几种数据类型。
1.namedtuple(): 生成可以使用名字来访问元素内容的tuple子类
2.deque: 双端队列，可以快速的从另外一侧追加和推出对象
3.Counter: 计数器，主要用来计数
4.OrderedDict: 有序字典
5.defaultdict: 带有默认值的字典
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;****&lt;strong&gt;具名元组(namedtuple)&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;pre&gt;&lt;code&gt;tuple是一个不可变的集合，namedtuple是一个函数，她用来构建一个自定义的tuple对象，
并且规定了tuple元素的个数，可通过属性而不是索引来引用tuple的某个元素。
我们可以通过namedtuple很方便的自定义一个数据类型，它具有tuple 的不变属性又可以根据属性来引用。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;****想表示空间坐标点x为1， y为2，z为5的坐标&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from collections import namedtuple
point = namedtuple(&#39;坐标&#39;,[&#39;x&#39;,&#39;y&#39;,&#39;z&#39;])  # 第二个参数既可以传可迭代对象
point1 = namedtuple(&#39;坐标&#39;,&#39;x y z&#39;)  # 也可以传字符串 但是字符串之间以空格隔开
p = point(1,2,5)
p1 = point1(2,3,6)print(p,p.x,p.y,p.z)  # 坐标(x=1, y=2, z=5) 1 2 5print(p1,p1.x,p1.y,p1.z)  # 坐标(x=2, y=3, z=6) 2 3 6
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;想表示一张黑桃A的扑克牌&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;card = namedtuple(&#39;扑克牌&#39;,&#39;color number&#39;)
card1 = namedtuple(&#39;扑克牌&#39;,[&#39;color&#39;,&#39;number&#39;])
A = card(&#39;♠&#39;,&#39;A&#39;)
B = card1(&#39;♠&#39;,&#39;A&#39;)print(A.color,A.number,A)  # ♠ A 扑克牌(color=&#39;♠&#39;, number=&#39;A&#39;)print(B.color,B.number,B)  # ♠ A 扑克牌(color=&#39;♠&#39;, number=&#39;A&#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;想表示一个城市&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】正则表达式与re模块</title>
      <link>https://zhong-er.com/posts/python%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%B8%8Ere%E6%A8%A1%E5%9D%97/</link>
      <pubDate>Wed, 17 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%B8%8Ere%E6%A8%A1%E5%9D%97/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第十三课(模块1).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907172541_862_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python正则表达式与re模块&lt;/strong&gt;************&amp;gt; &amp;raquo;转到****&lt;a href=&#34;https://mubu.com/doc/1cDg8PhNk8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;&lt;strong&gt;思维导图&lt;/strong&gt;&lt;/strong&gt;************************************&lt;/a&gt;&lt;strong&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;/strong&gt;********&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11196211.html&#34; title=&#34;博客园&#34;&gt;博客园&lt;/a&gt;****&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;正则表达式与re模块的关系&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.正则表达式是一门独立的技术，任何语言均可使用&lt;/p&gt;
&lt;p&gt;2.python中要想使用正则表达式需要通过re模块&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;正则表达式应用场景&lt;/strong&gt;&lt;br&gt;
推荐书籍：正则指引&lt;/p&gt;
&lt;p&gt;1.爬虫&lt;/p&gt;
&lt;p&gt;2.数据分析&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;字符组概念&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在同一个位置可能出现的各种字符组成了一个字符组，在正则表达式中用[]表示(一个字符组每次只能匹配一个字符)&lt;/p&gt;
&lt;p&gt;小例子&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;匹配0-9数字([0123456789]也支持简写[0-9])(如果想匹配横杠,转义即可)
匹配A-Z字母(依据上面的简写规则[A-Z])
匹配a-z字母(依据上面的简写规则[a-z])
ps:这种上面到上面的范围必须是从小到大[a-Z]不行，[A-z]可以(但是内部有几个特殊符号)，因为内部对应的asicc码A在所有字母里面最小，z在所有字母里面最大
&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;正则&lt;/th&gt;
					&lt;th&gt;待匹配字符&lt;/th&gt;
					&lt;th&gt;匹配结果&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;[0123456789]&lt;/td&gt;
					&lt;td&gt;8&lt;/td&gt;
					&lt;td&gt;True&lt;/td&gt;
					&lt;td&gt;在一个字符组里枚举合法的所有字符，字符组里的任意一个字符&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;和&amp;quot;待匹配字符&amp;quot;相同都视为可以匹配&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;[0123456789]&lt;/td&gt;
					&lt;td&gt;a&lt;/td&gt;
					&lt;td&gt;False&lt;/td&gt;
					&lt;td&gt;由于字符组中没有&amp;quot;a&amp;quot;字符，所以不能匹配&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;[0-9]| 7| True| 也可以用-表示范围,[0-9]就和[0123456789]是一个意思&lt;/p&gt;
&lt;p&gt;[a-z]| s| True| 同样的如果要匹配所有的小写字母，直接用[a-z]就可以表示&lt;/p&gt;
&lt;p&gt;[A-Z]| B| True| [A-Z]就表示所有的大写字母&lt;/p&gt;
&lt;p&gt;[0-9a-fA-f]| e| True| 可以匹配数字，大小写形式的a～f，用来验证十六进制字符&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;字符&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;元字符&lt;br&gt;
| 匹配内容&lt;/p&gt;
&lt;p&gt;&amp;mdash;|&amp;mdash;&lt;br&gt;
. | 匹配除换行符以外的任意字符&lt;br&gt;
\w| 匹配字母或数字或下划线&lt;br&gt;
\s| 匹配任意的空白符&lt;br&gt;
\d| 匹配数字&lt;br&gt;
\n| 匹配一个换行符&lt;br&gt;
\t| 匹配一个制表符&lt;br&gt;
\b| 匹配一个单词的结尾&lt;br&gt;
^| 匹配字符串的开始&lt;br&gt;
$| 匹配字符串的结尾&lt;br&gt;
\W| 匹配非字母或数字或下划线&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】模块</title>
      <link>https://zhong-er.com/posts/python%E6%A8%A1%E5%9D%97/</link>
      <pubDate>Tue, 16 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E6%A8%A1%E5%9D%97/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第十三课(模块1).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907164750_6602_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python模块&lt;/strong&gt;******&amp;gt; &amp;raquo;转到**&lt;a href=&#34;https://mubu.com/doc/2SBPS0hBq8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;********************&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11203235.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;************&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.什么是模块？&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1模块就是一系列工能的结合体
2模块的三种来源：
    1.内置的(python解释器自带)
    2.第三方的(别人写的)
    3.自定义的(你自己写的)
3模块的四种表现形式
    1.使用python编写的py文件(也就意味着py文件也可以称之为模块:一个py文件也可以称之为一个模块)
    2.已被编译为共享库或DLL的C或C++扩展(了解)
    3.包好一组模块的包：把一系列模块组织到一起的文件夹(文件夹下有一个__init__.py文件，该文件夹称之为包) 包:一系列py文件的结合体
    4.使用C编写并链接到python解释器的内置模块
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;2.为什么要用模块&lt;/strong&gt;**？**&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1.从文件级别组织程序，更方便管理。
当多个文件中都需要使用相同的方法的时候 可以将该公共的方法写到一个py文件中，其他的文件以模块的形式导过去直接调用即可
2.拿来主义，提升开发效率
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;3如何使用模块？&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1.import的使用
    模块可以包含可执行的语句和函数的定义，这些语句的目的是初始化模块，它们只在模块名第一次遇到导入import语句时才执行
2.在第一次导入模块时会做三件事，重复导入会直接引用内存中已经加载好的结果
    1.首先创建一个执行文件(run.py)的名称空间，执行模块文件
在模块中定义的函数和方法若是使用到了global时访问的就是这个名称空间
    2.运行模块文件(md.py)中的代码将产生的名字与值存放到执行文件(run.py)的名称空间中
        在新创建的命名空间中执行模块中包含的代码
    3.在执行文件中产生一个执行指向名称空间的名字(md)
        创建名字来引用该命名空间
3from...import...句式缺点:
    1.访问模块中的名字不需要加模块名前缀
    2.在访问模块中的名字可能会与当前执行文件中的名字冲突
4补充知识点：
    __name__
        当文件被当做执行文件执行的时候__name__打印的结果是__main__
        当文件被当做模块导入的时候__name__打印的结果是模块名(没有后缀)
    __all__
        __all__可以指定当所在py文件被当做模块导入的时候,可以限制导入者能够拿到的名字个数
    from md1 import *
        一次性将md1模块中的名字全部加载过来 不推荐使用 并且你根本不知道到底有哪些名字可以用
    异常有两大类
        1.语法结构错误:需要你当场修改 异常捕获没法完成
        2.逻辑错误:异常捕获可以处理
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;4.循环导入&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1.如果出现循环导入问题 那么一定是你的程序设计的不合理。循环导入问题应该在程序设计阶段就应该避免。
2.解决循环导入问题的方式
    1.方式1：将循环导入的句式写在文件最下方()
    2.方式2：函数内导入模块
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;5.模块的查找顺序&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1.先从内存中找
2.再从内置中找
3.最后环境变量(sys.path)中找
    一定要分清楚谁是执行文件谁是被导入文件sys.path返回的是一个大列表,里面放了一对文件路径,第一个路径永远是执行文件所在的文件夹注意:py文件名不应该与模块名(内置的,第三方)冲突
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;6.绝对导入与相对导入&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1绝对导入
    绝对导入必须依据执行文件所在的文件夹路径为准
    绝对导入无论在执行文件中还是被导入文件都适用
2相对导入
    .代表的当前路径
    ..代表的上一级路径
    ...代表的是上上一级路径
    注意相对导入不能再执行文件中使用
    相对导入只能在被导入的模块中使用,使用相对导入就不需要考虑执行文件到底是谁，只需要知道模块与模块之间路径关系
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;7.软件开发规范&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】迭代器/生成器</title>
      <link>https://zhong-er.com/posts/python%E8%BF%AD%E4%BB%A3%E5%99%A8%E7%94%9F%E6%88%90%E5%99%A8/</link>
      <pubDate>Mon, 15 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E8%BF%AD%E4%BB%A3%E5%99%A8%E7%94%9F%E6%88%90%E5%99%A8/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第十二课(迭代器_生成器).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907152595_5668_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python迭代器/生成器&lt;/strong&gt;******&amp;gt; &amp;raquo;转到**&lt;a href=&#34;https://mubu.com/doc/3Hk6DuxYi8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11191167.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.迭代&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.1什么是迭代：&lt;/p&gt;
&lt;p&gt;更新换代(重复)的过程，每次迭代都必须基于上一次的结果&lt;/p&gt;
&lt;p&gt;1.2什么是迭代器：&lt;/p&gt;
&lt;p&gt;迭代取值的工具&lt;/p&gt;
&lt;p&gt;1.3为什么要有迭代器：&lt;/p&gt;
&lt;p&gt;迭代器提供了一种不依赖于索引取值的方式&lt;br&gt;
对于序列类型：字符串、列表、元组，我们可以使用索引的方式迭代取出其包含的元素。但对于字典、集合、文件等类型是没有索引的，若还想取出其内部包含的元素，则必须找出一种不依赖于索引的迭代方式，这就是迭代器&lt;/p&gt;
&lt;p&gt;1.4什么是可迭代对象：&lt;/p&gt;
&lt;p&gt;可迭代对象指的是内置有__iter__方法的对象，即obj.&lt;strong&gt;iter&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.5什么是迭代器对象：&lt;/p&gt;
&lt;p&gt;可迭代对象执行obj.&lt;strong&gt;iter&lt;/strong&gt;()得到的结果就是迭代器对象。而迭代器对象指的是即内置有__iter__又内置有__next__方法的对象。&lt;/p&gt;
&lt;p&gt;1.6注意：&lt;/p&gt;
&lt;p&gt;迭代器对象一定是可迭代对象，而可迭代对象不一定是迭代器对象&lt;/p&gt;
&lt;p&gt;需要迭代取值的数据类型：字符串str、列表list、元组tuple、字典dict、集合set、文件对象&lt;/p&gt;
&lt;p&gt;文件对象执行内置的__iter__之后还是本身 没有任何变化，文件对象本身就是迭代器对象&lt;/p&gt;
&lt;p&gt;针对双下线开头双下划线结尾的方法，推荐读:双下+方法名&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.迭代器取值：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;迭代器取值 调用__next__&lt;/p&gt;
&lt;p&gt;迭代器对象无论执行多少次__iter__方法得到的还是迭代器对象本身&lt;/p&gt;
&lt;p&gt;2.1异常报错StopIteration：取完了&lt;/p&gt;
&lt;p&gt;2.2异常处理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;while True: 
    try: 
        print(iter_d.__next__()) 
    except StopIteration: 
        print(&#39;老母猪生不动了&#39;)
    break
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;2.3迭代器取值的特点：只能往后依次取，不能后退&lt;/p&gt;
&lt;p&gt;2.4迭代器取值的优点：&lt;/p&gt;
&lt;p&gt;1.不依赖于索引取值&lt;/p&gt;
&lt;p&gt;2.内存中永远只占一份空间,不会导致内存溢出&lt;/p&gt;
&lt;p&gt;2.5迭代器取值的缺点：&lt;/p&gt;
&lt;p&gt;1.不能够获取指定的元素&lt;/p&gt;
&lt;p&gt;2.取完之后会报StopIteration错&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.for循环的本质&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.将in后面的对象调用__iter__转换成迭代器对象&lt;/p&gt;
&lt;p&gt;2.调用__next__迭代取值&lt;/p&gt;
&lt;p&gt;3.内部有异常捕获StopIteration,当__next__报这个错 自动结束循环&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4.生成器&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;只要函数内部包含有yield关键字，那么函数名()的到的结果就是生成器，并且不会执行函数内部代码&lt;/p&gt;
&lt;p&gt;生成器就是迭代器，可以用__next__方法取值&lt;/p&gt;
&lt;p&gt;yield后面跟的值就是调用迭代器__next__方法你能得到的值&lt;/p&gt;
&lt;p&gt;yield既可以返回一个值也可以返回多个值，并且多个值也是按照元组的形式返回&lt;/p&gt;
&lt;p&gt;可以用.send给yield左边的变量传参，但必须先将代码运行至yield才能为期传值&lt;/p&gt;
&lt;p&gt;yeild&lt;/p&gt;
&lt;p&gt;1.帮你提供了一种自定义生成器方式&lt;/p&gt;
&lt;p&gt;2.会帮你将函数的运行状态暂停住&lt;/p&gt;
&lt;p&gt;3.可以返回值&lt;/p&gt;
&lt;p&gt;yeid与return异同:&lt;/p&gt;
&lt;p&gt;相同点：都可以返回值,并且都可以返回多个&lt;/p&gt;
&lt;p&gt;不同点：yield可以返回多次值,而return只能返回一次函数立即结束，yield还可以接受外部传入的值&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5.生成器表达式&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;例如：res = (i for i in range(1,10) if i != 4)&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】函数</title>
      <link>https://zhong-er.com/posts/46-python%E5%87%BD%E6%95%B0/</link>
      <pubDate>Fri, 12 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/46-python%E5%87%BD%E6%95%B0/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第十一课(函数4).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907129002_6648_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python函数 &amp;raquo;&amp;gt;转到&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/1IPnO44N88&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11178851.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;递归函数&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;函数在调用阶段直接或间接的又调用自身&lt;/p&gt;
&lt;p&gt;如果一个函数在内部调用自身本身，这个函数就是递归函数。&lt;/p&gt;
&lt;p&gt;举例&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 举个例子，我们来计算阶乘n! = 1 x 2 x 3 x ... x n，用函数fact(n)表示，可以看出：
# fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n
# 所以，fact(n)可以表示为n x fact(n-1)，只有n=1时需要特殊处理。
# 于是，fact(n)用递归的方式写出来就是：
def fact(n):
    if n==1:
        return 1
    return n * fact(n - 1)
# 如果我们计算fact(5)，可以根据函数定义看到计算过程如下：
===&amp;gt; fact(5)
===&amp;gt; 5 * fact(4)
===&amp;gt; 5 * (4 * fact(3))
===&amp;gt; 5 * (4 * (3 * fact(2)))
===&amp;gt; 5 * (4 * (3 * (2 * fact(1))))
===&amp;gt; 5 * (4 * (3 * (2 * 1)))
===&amp;gt; 5 * (4 * (3 * 2))
===&amp;gt; 5 * (4 * 6)
===&amp;gt; 5 * 24
===&amp;gt; 120
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;扩展 import sys&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】装饰器</title>
      <link>https://zhong-er.com/posts/python%E8%A3%85%E9%A5%B0%E5%99%A8/</link>
      <pubDate>Fri, 12 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E8%A3%85%E9%A5%B0%E5%99%A8/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第十课(函数3).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907122677_6873_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python装饰器&lt;/strong&gt;&amp;gt; &amp;raquo;转到****&lt;a href=&#34;https://mubu.com/doc/IAt9WRlRa&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;********&lt;/a&gt;&lt;strong&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11178817.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;闭包函数&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.定义在函数内部的函数&lt;/p&gt;
&lt;p&gt;2.内部函数内部函数引用了外部函数名称空间作用域的名字&lt;/p&gt;
&lt;p&gt;只要满足以上两点都叫做闭包函数&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def func():
    name = jason&#39;  # 先在内部找name没有再往上层找 有了就停止查找
    def inner():
        print(name)  # 现在内部找name没有再往上层找
    return inner
f = func()  # f获取到的是inner的内存地址
f()  # 相当于执行 inner()
# 函数在定义阶段名字的查找孙旭就已经固定死了，不会因为函数调用位置的变化而变化
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;给函数传参的两种方式&lt;/p&gt;
&lt;p&gt;1.直接传参&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def index(name):
    print(name)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;2.闭包&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def outter(name):
    # name = &#39;jason&#39;
    def index():
        print(name)
    return index
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;装饰器&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;器：就是一个工具&lt;/p&gt;
&lt;p&gt;装饰：就是给被装饰对象添加新的功能&lt;/p&gt;
&lt;p&gt;开放封闭原则：&lt;/p&gt;
&lt;p&gt;开放：对扩展开放&lt;/p&gt;
&lt;p&gt;封闭：对修改封闭&lt;/p&gt;
&lt;p&gt;装饰器(可调用对象)必须遵循的两个原则：&lt;/p&gt;
&lt;p&gt;1.不改变被装饰对象的源代码&lt;/p&gt;
&lt;p&gt;2.不改变被装饰对象(可调用对象)调用方法&lt;/p&gt;
&lt;p&gt;可调用：callable&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def new():
    print(&#39;这是原始函数&#39;)

def outter(func):
    def inner():
        print(&#39;这是内部函数，这里可以加新功能&#39;)
        func()  # 这里的func是你想调用的最原始的函数的内存地址,加上()直接调用
        print(&#39;这是内部函数，这里可以加新功能&#39;)
    return inner  # 这里不加括号 返回的是inner函数的内存地址
new = outter(new)  # 括号内的new指向的是最原始的new函数的内存地址，前面的new获取的是outter函数的返回值，返回值我们自定义了返回 inner函数的内存地址
# 总结：前面的new获取的是inner的内存地址，后面括号内的new指向的就是最原始的new的内存地址
new()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;扩展：import time&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】名称空间与作用域/函数的嵌套</title>
      <link>https://zhong-er.com/posts/python%E5%90%8D%E7%A7%B0%E7%A9%BA%E9%97%B4%E4%B8%8E%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%87%BD%E6%95%B0%E7%9A%84%E5%B5%8C%E5%A5%97/</link>
      <pubDate>Wed, 10 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E5%90%8D%E7%A7%B0%E7%A9%BA%E9%97%B4%E4%B8%8E%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%87%BD%E6%95%B0%E7%9A%84%E5%B5%8C%E5%A5%97/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第九课(函数2).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907105483_5533_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python名称空间与作用域/函数的嵌套&lt;/strong&gt;** &amp;raquo;&amp;gt;转到**&lt;a href=&#34;https://mubu.com/doc/25A0qDQkG8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;********&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到****&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11158059.html&#34;&gt;博客园&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;命名关键字参数&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在函数定义阶段，写在*和**可变长参数之间的形参&lt;/p&gt;
&lt;p&gt;在给命名关键字参数传值的时候，只能用关键字为期传值&lt;/p&gt;
&lt;p&gt;在定义阶段 给你感觉好像是z是默认值参数，放在了m这个位置参数的前面了，应该报错&lt;/p&gt;
&lt;p&gt;其实z和m都是命名关键字参数，不是默认值参数和位置参数&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def func(x,y=1,*args,z=3,m,**kwargs):
    print(x,y)
    print(args)
    print(z,m)
    print(kwargs)
func(1,2,1,2,3,4,5,6,7,78,8,9,0,z=69,m=999,o=666999,l = 999666)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;函数对象&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;函数是第一类对象：函数名指向的值可以被当中的参数传递&lt;/p&gt;
&lt;p&gt;1.函数名可以被传递&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name = &#39;jason&#39;
x = name
print(x)
print(id(x))
def func():
    print(&#39;from func&#39;)
# print(func)
print(id(func))
f = func

func()
print(f)
f()  # 其实指向的也是函数func指向函数体代码的内存地址
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;2.函数名可以被党组参数传递给其他函数&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def func():
    print(&#39;from func&#39;)

def index(args):
    print(args)
    args()
    print(&#39;from index&#39;)
# index(1)
index(func)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;3.函数名可以被当做函数的返回值&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def index():
    print(&#39;index&#39;)


def func():
    print(&#39;func&#39;)
    return index
res = func()
print(res)
res()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;4.函数名可以被当做容器类型的参数&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】函数</title>
      <link>https://zhong-er.com/posts/43-python%E5%87%BD%E6%95%B0/</link>
      <pubDate>Tue, 09 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/43-python%E5%87%BD%E6%95%B0/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第八课(函数).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201907099354_6068_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python函数 &lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/15Mo0f_bV8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;&lt;strong&gt;思维导图&lt;/strong&gt;&lt;/strong&gt;********&lt;/a&gt;&lt;strong&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11158059.html&#34;&gt;&lt;strong&gt;&lt;strong&gt;博客园&lt;/strong&gt;&lt;/strong&gt;****************&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;函数的返回值&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;函数内要想返回给调用者值 必须用关键字return&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;不写return:函数默认返回None&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def func():
    print(&#39;hahaha&#39;)
res = func()
print(res)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;只写return:return除了可以返回值之外，还可以直接结束整个函数的运行&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;只写return 返回的也是None(None就表示什么都没有)&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;只写return 返回的也是None(None就表示什么都没有)
def func():
    l = [&#39;jason&#39;,&#39;egon&#39;,&#39;tank&#39;]
    while True:
        for i in l:
            if i == &#39;egon&#39;:  # 当i为egon的时候 直接结束函数运行
                # break
                return
                # print(&#39;asdasdkljlsjadl&#39;)  # 这一行代码拥有都不会运行
            print(i)
res = func()
print(res)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;写return None:跟上面的只写return是一样的&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def func():
    return None
res = func()
print(res)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;写return返回一个值:这个值可以是python任意数据类型&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def func():
    return &#39;123&#39;
def func1():
    return [1,2,3]
def func2():
    return {&#39;name&#39;:&#39;jason&#39;}
def func3():
    return (1,)
def func4():
    return {1,2,3,4,5}
def func5():
    return True
print(func(),func1(),func2(),func3(),func4(),func5())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;写return返回多个值:return会自动将多个值以元组的形式返回给调用者&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】文件操作/函数前戏</title>
      <link>https://zhong-er.com/posts/python%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C%E5%87%BD%E6%95%B0%E5%89%8D%E6%88%8F/</link>
      <pubDate>Mon, 08 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C%E5%87%BD%E6%95%B0%E5%89%8D%E6%88%8F/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第07课(文件操作_函数前戏).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908067592_1286_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python文件操作/函数前戏 &amp;raquo;&amp;gt;转到&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/2qvfaKltq8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;********&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11151888.html&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;文件操作模式补充&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;+&amp;quot; 表示可以同时读写某个文件
r+， 读写【可读，可写】
w+，写读【可读，可写】
a+， 写读【可读，可写】
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;文件内光标移动&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;一: read(3)：
1. 文件打开方式为文本模式时，代表读取3个字符
2. 文件打开方式为b模式时，代表读取3个字节
二: 其余的文件内光标移动都是以字节为单位如seek，tell，truncate
注意：
1. seek有三种移动方式0，1，2，其中1和2必须在b模式下进行，但无论哪种模式，都是以bytes为单位移动的
2. truncate是截断文件，所以文件的打开方式必须可写，但是不能用w或w+等方式打开，因为那样直接清空文件了，所以truncate要在r+或a或a+等模式下测试效果
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;检测文件内容&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;with open(r&#39;test01.txt&#39;,&#39;rb&#39;) as f:
    # 先将光标移动到文件末尾
    f.seek(0,2)
    while True:
        res = f.readline()
        # 查看光标移动了多少位 bytes
        # print(f.tell())
        if res:
            print(&amp;quot;新增的文件内容:%s&amp;quot;%res.decode(&#39;utf-8&#39;))
            # 说明有人操作当前文件
        # else:
        #     # 说明文件没有被任何人操作
        #     print(&#39;暂无其他人操作该文件&#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;截断文件&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;with open(r&#39;test&#39;,&#39;a&#39;,encoding=&#39;utf-8&#39;) as f:
    f.truncate(6)  # 接收的字节的长度 整型
    # 保留0~6字节数 后面的全部删除(截断)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改文件&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】字符编码/文件操作</title>
      <link>https://zhong-er.com/posts/python%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C/</link>
      <pubDate>Fri, 05 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C/</guid>
      <description>&lt;h2&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&#34;Python第06课(字符编码_文件操作).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908063789_220_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python字符编码/文件操作 &amp;raquo;&amp;gt;转到&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/2mwGPbqdZ8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11140402.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;字符编码&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 字符编码针对的是文字。
# 字符编码只跟文本文件有关。
# 文本编辑器的输入和输出是两个过程。
# 字符编码表就是字符与数字的对应关系

ASCII码表 用八位二进制表示一个英文字符

GBK 用2Bytes表示一个中文字符，还是用1Bytes表示一个英文字母。最多能表示65535个字符

Unicode万国码 统一用2Bytes表示所有的字符
    1.浪费存储空间
    2.IO次数增加，程序运行效率降低(致命)
    
# 当内存中的unicode编码格式数据存到硬盘的时候，会按照utf-8编码

# 会将unicode的英文字符由原来的2Bytes变成1Bytes
# 会将unicode中文字符由原来的2Bytes变成3Bytes
# 现在的计算机内存都是unicode，硬盘都是utf-8

unicode的两个特点
    1.用户在输入的时候，无论输什么字符都能够兼容万国字符
    2.其他国家编码的数据由硬盘读到内存的时候unicode与其他各个国家的编码都有对应关系
    
# 数据由内存保存到硬盘
    内存中的unicode格式二进制数字 &amp;gt;&amp;gt;&amp;gt;编码(encode)&amp;gt;&amp;gt;&amp;gt;utf-8格式的二进制数据
# 硬盘中的数据由硬盘读到内存
    硬盘中的utf-8格式的二进制数据&amp;gt;&amp;gt;&amp;gt;解码(decode)&amp;gt;&amp;gt;&amp;gt;内存中unicode格式的二进制数据
    
# 保证不乱码在于文本文件以什么编码编的就以什么编码解

# python2将py文件按照文本文件读入解释器中默认使用ASCII码
# python3将py文件按照文本文件读入解释器中默认使用utf-8

# 文件头 # coding:utf-8 因为所有的编码都支持英文字符,所以文件头才能够正常生效
# python3中字符串默认就是unicode编码格式的二进制数
# pycharm终端用的是utf-8格式，windows终端采用的是gbk格式。

encode() # 将unicode编码成可以存储和传输的utf-8的二进制数据
# bytes类型  字节串类型  你就把它当成二进制数据即可
decode()  # 将硬盘中的utf-8格式的二进制数据解码成unicode格式的二进制数据

x = &#39;上&#39;
res1 = x.encode(&#39;gbk&#39;)  # 将unicode编码成可以存储和传输的utf-8的二进制数据
print(res1)  # b&#39;\xe4\xb8\x8a&#39;
# bytes类型  字节串类型  你就把它当成二进制数据即可
res2 = res1.decode(&#39;gbk&#39;)  # 将硬盘中的utf-8格式的二进制数据解码成unicode格式的二进制数据
print(res2)


# 补充:
# 你a他
# 1Bytes|1Bytes|1Bytes|1Bytes|1Bytes|1Bytes|1Bytes
# 1+7bit|1+7bit|1+7bit|1+7bit|1+7bit|1+7bit|1+7bit
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;文件处理&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】列表/字典/元组/集合</title>
      <link>https://zhong-er.com/posts/python%E5%88%97%E8%A1%A8%E5%AD%97%E5%85%B8%E5%85%83%E7%BB%84%E9%9B%86%E5%90%88/</link>
      <pubDate>Thu, 04 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E5%88%97%E8%A1%A8%E5%AD%97%E5%85%B8%E5%85%83%E7%BB%84%E9%9B%86%E5%90%88/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第05课(数据类型5).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908067586_2449_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python列表/字典/元组/集合 &amp;raquo;&amp;gt;转到&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/3wTzttZOc8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;********&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11133594.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;列表list&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;count()用来统计列表某个元素的个数&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; l = [1,2,3,4,5,6,7]
&amp;gt;&amp;gt;&amp;gt; res = l.count(8)
&amp;gt;&amp;gt;&amp;gt; print(res)
0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;clear()用来清除列表元素&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; res = l.clear()
&amp;gt;&amp;gt;&amp;gt; print(res)
None
&amp;gt;&amp;gt;&amp;gt; print(l)
[]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;reverse()用来将列表反转&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; l = [1,2,3,4,5,6,7]
&amp;gt;&amp;gt;&amp;gt; print(id(l))
2271674158920
&amp;gt;&amp;gt;&amp;gt; l.reverse()
&amp;gt;&amp;gt;&amp;gt; print(l)
[7, 6, 5, 4, 3, 2, 1]
&amp;gt;&amp;gt;&amp;gt; print(id(l))
2271674158920
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;sort()按升序将列表元素排序&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; l.sort()
&amp;gt;&amp;gt;&amp;gt; print(l)
[1, 2, 3, 4, 5, 6, 7]
&amp;gt;&amp;gt;&amp;gt; print(id(l))
2271674158920
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;队列：先进先出&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】数据类型</title>
      <link>https://zhong-er.com/posts/python%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/</link>
      <pubDate>Wed, 03 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第04课(数据类型).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908064143_4756_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python数据类型 &amp;raquo;&amp;gt;转到&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/3BB-YIvKm8&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11128314.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;整型(int)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;用途：记录QQ号、手机号、身份证号等&lt;/p&gt;
&lt;p&gt;定义：age = 18&lt;/p&gt;
&lt;p&gt;常用操作+内置的方法&lt;/p&gt;
&lt;p&gt;int只能转存数字的字符串，小数点都不行&lt;/p&gt;
&lt;p&gt;进制转换&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; print(int(&#39;1100&#39;,2))  # 二进制转十进制  0,1
12
&amp;gt;&amp;gt;&amp;gt; print(int(&#39;14&#39;,8))  # 八进制转十进制  0-7
12
&amp;gt;&amp;gt;&amp;gt; print(int(&#39;c&#39;,16))  # 十六进制转十进制 0-9 A-F
12
# int可以传第一个参数，表示的是第一个参数到底是什么进制  然后转成十进制

&amp;gt;&amp;gt;&amp;gt; print(bin(12))  # 10进制转二进制
0b1100  # 0b1100  0b表示后面的数字是二进制数
&amp;gt;&amp;gt;&amp;gt; print(oct(12))  # 10进制转八进制
0o14  # 0o14  0o表示后面的数字是八进制数
&amp;gt;&amp;gt;&amp;gt; print(hex(12))  # 10进制转16进制
0xc  # 0xc  0x表示后面的数字是十六进制数
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;有序：但凡有索引的数据都是有序的&lt;/p&gt;
&lt;p&gt;不可变：值改变的情况下，id一定变&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;浮点型(float)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;用途：记录薪资、身高、体重等&lt;/p&gt;
&lt;p&gt;定义：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;salary = 1.1 # salary = float(1.1)

&amp;gt;&amp;gt;&amp;gt; res = float(&#39;1.11&#39;)
&amp;gt;&amp;gt;&amp;gt; print(type(res))
&amp;lt;class &#39;float&#39;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;有序：但凡有索引的数据都是有序的&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】流程控制</title>
      <link>https://zhong-er.com/posts/python%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6/</link>
      <pubDate>Tue, 02 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第03课(流程控制).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908064421_9543_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python流程控制 &amp;raquo;&amp;gt;转到&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/3DKlGWgq58&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11120996.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;********&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;if判断&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;判断失误的对错，真假，是否可行&lt;/p&gt;
&lt;p&gt;固定语法&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if 条件:
    代码1
    代码2
    代码3
    代码4
    ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;python的缩进表示代码的归属&lt;/p&gt;
&lt;p&gt;同一缩进的代码，称之为代码块&lt;/p&gt;
&lt;p&gt;补充：布尔值位False数据由哪些：0,None,&amp;rsquo; &amp;lsquo;,[ ],{ }&lt;/p&gt;
&lt;p&gt;布尔值也可以直接用来判断&lt;/p&gt;
&lt;p&gt;变量名也可以用来判断，因为变量名指向的值对应的就是True或False&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;else 语法&lt;/strong&gt; # 不能单独使用，必须和if，while，for配合使用&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if 条件:
    代码1
    代码2
    代码3
    代码4
    ...
else:  # 不能单独使用，必须和if，while，for配合使用
    代码1
    代码2
    代码3
    代码4
    ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;if elif else 语法&lt;/strong&gt; ：同一级别配合使用的时候，只会指向一个代码块&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if 条件:
    代码1
    代码2
    代码3
    代码4
    ...
elif 条件:
    代码1
    代码2
    代码3
    代码4
    ...
else:  # 不能单独使用，必须和if，while，for配合使用
    代码1
    代码2
    代码3
    代码4
    ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;走了if就不会走elif else，走了elif就不会走else，if看到没走，走了else说明if elif都没走，都不满足if elif的条件&lt;/p&gt;</description>
    </item>
    <item>
      <title>【Python】输入输出/数据类型/运算符</title>
      <link>https://zhong-er.com/posts/python%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E8%BF%90%E7%AE%97%E7%AC%A6/</link>
      <pubDate>Mon, 01 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E8%BF%90%E7%AE%97%E7%AC%A6/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第02课(输入输出_数据类型_运算符).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908066557_7614_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python输入输出/数据类型/运算符 &amp;raquo;&amp;gt;转到&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/SDSzaoBba&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;********&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11116171.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;********&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Python的注释&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;单行注释# 和多行注释&amp;rsquo;&amp;rsquo;&amp;rsquo; &amp;rsquo;&amp;rsquo;&#39;&#39;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;输入&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;python3中的input全部存成字符串类型&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;python2中需要认为告诉input输入的什么数据类型&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt; name = input(&amp;lsquo;please input&amp;raquo;&amp;gt;:&amp;rsquo;)
please input&amp;raquo;&amp;gt;:jason
Traceback (most recent call last):
File &amp;ldquo;&lt;stdin&gt;&amp;quot;, line 1, in &lt;module&gt;
File &amp;ldquo;&lt;string&gt;&amp;quot;, line 1, in &lt;module&gt;
NameError: name &amp;lsquo;jason&amp;rsquo; is not defined
 name = input(&amp;lsquo;please input&amp;raquo;&amp;gt;:&amp;rsquo;)
please input&amp;raquo;&amp;gt;:&amp;rsquo;egon&amp;rsquo;
 name
&amp;rsquo;egon&amp;rsquo;
 type(name)
&amp;lt;type &amp;lsquo;str&amp;rsquo;&amp;gt;
 name = input(&amp;lsquo;please input&amp;raquo;&amp;gt;:&amp;rsquo;)
please input&amp;raquo;&amp;gt;:[1,2,3,4]
 name
[1, 2, 3, 4]
 type(name)
&amp;lt;type &amp;rsquo;list&amp;rsquo;&amp;gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;raw_input()会统一存为字符串&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt; name1 = raw_input(&amp;rsquo;&amp;raquo;&amp;raquo;&amp;raquo;&amp;raquo;&amp;raquo;&amp;raquo;&amp;raquo;&amp;raquo;&amp;raquo;:&amp;rsquo;)&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;:jason
 name1
&amp;lsquo;jason&amp;rsquo;
 type(name1)
&amp;lt;type &amp;lsquo;str&amp;rsquo;&amp;gt;
 name1 = raw_input(&amp;rsquo;&amp;raquo;&amp;raquo;&amp;raquo;&amp;raquo;&amp;raquo;&amp;raquo;&amp;raquo;&amp;raquo;&amp;raquo;:&amp;rsquo;)
:[1,2,3,4,5]
 name1
&amp;lsquo;[1,2,3,4,5]&amp;rsquo;
 type(name1)
&amp;lt;type &amp;lsquo;str&amp;rsquo;&amp;gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>【Python】计算机发展史/变量/垃圾回收机制</title>
      <link>https://zhong-er.com/posts/python%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%8F%91%E5%B1%95%E5%8F%B2%E5%8F%98%E9%87%8F%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6/</link>
      <pubDate>Fri, 28 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%8F%91%E5%B1%95%E5%8F%B2%E5%8F%98%E9%87%8F%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python第01课(计算机发展史_变量_垃圾回收.png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908062863_1504_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python计算机发展史/变量/垃圾回收机制 &amp;raquo;&amp;gt;转到&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/2rsFXAwli8&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;********&lt;/a&gt;&lt;strong&gt;&amp;gt; &amp;raquo;转到&lt;/strong&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11103673.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;********&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11103673.html&#34; title=&#34;博客园&#34;&gt;****&lt;/a&gt;&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11103673.html&#34; title=&#34;博客园&#34;&gt;&lt;/a&gt;&lt;strong&gt;编程语言发展史&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;机器语言&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;站在奴隶主的角度说奴隶主的话&lt;/p&gt;
&lt;p&gt;1.编译型(类似于谷歌翻译)&lt;/p&gt;
&lt;p&gt;2.解释型(类似于同声传译)&lt;/p&gt;
&lt;p&gt;PS:一次翻译之后，就可以拿着翻译之后的结果多次运行&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;汇编语言&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;用简单的英文标签来表示二进制数，直接操作硬件&lt;/p&gt;
&lt;p&gt;优点：开发效率高于机器语言&lt;/p&gt;
&lt;p&gt;缺点：执行效率较机器语言低&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;高级语言&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;站在奴隶主的角度说奴隶主的话&lt;/p&gt;
&lt;p&gt;1.编译型(类似于谷歌翻译)&lt;/p&gt;
&lt;p&gt;一次翻译之后，就可以拿着翻译之后的结果多次运行&lt;/p&gt;
&lt;p&gt;编译的过程需要用到编译器&lt;/p&gt;
&lt;p&gt;优点：执行效率高&lt;/p&gt;
&lt;p&gt;缺点：开发效率低&lt;/p&gt;
&lt;p&gt;2.解释型(类似于同声传译)&lt;/p&gt;
&lt;p&gt;一行一行的翻译(读一行翻译一行)&lt;/p&gt;
&lt;p&gt;解释的过程需要用到解释器&lt;/p&gt;
&lt;p&gt;优点：开发效率高&lt;/p&gt;
&lt;p&gt;缺点：执行效率低&lt;/p&gt;
&lt;p&gt;PS:&lt;/p&gt;
&lt;p&gt;学习难度：高级语言&amp;raquo;&amp;gt;汇编语言&amp;raquo;&amp;gt;机器语言&lt;/p&gt;
&lt;p&gt;执行效率：机器语言&amp;raquo;&amp;gt;汇编语言&amp;raquo;&amp;gt;高级语言&lt;/p&gt;
&lt;p&gt;开发效率：机器语言&amp;raquo;&amp;gt;汇编语言&amp;raquo;&amp;gt;高级语言&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;python是解释型语言&lt;/p&gt;
&lt;p&gt;1.胶水语言&lt;/p&gt;
&lt;p&gt;2.调包侠&lt;/p&gt;
&lt;p&gt;python解释器，环境变量配置，多版本共存&lt;/p&gt;
&lt;p&gt;在IT行业不要贸然尝试用最新版本的软件！！！&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一个Python程序&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.交互式&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;优点：输入内容立刻就有对应的返回结果&lt;/p&gt;
&lt;p&gt;缺点：无法永久保存数据&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.命令行(文件形式)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;优点：可以永久保存数据&lt;/p&gt;
&lt;p&gt;缺点：暂时来看运行该文件有点麻烦&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PS：文件后缀名&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;仅仅是给人看的&lt;/p&gt;
&lt;p&gt;你所认为的不同的文件后缀有不同的功能那是程序员自己写的&lt;/p&gt;
&lt;p&gt;python文件默认的后缀名就是.py结尾&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;运行一个py文件需要走的步骤(&lt;/strong&gt;*&lt;strong&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.将python解释器代码从硬盘督导内存(就等价于双击了word图标)&lt;/p&gt;
&lt;p&gt;2.将你写好的py文件由应哦按读到内存(就等价于你双击了一个word文档)&lt;/p&gt;
&lt;p&gt;3.解释器解释读取py文件中的内容，解释成计算机能够识别的语句(如果是一个普通文本文件，仅仅只会将文件内容展示到屏幕上给用户查看，不会检测翻译文件内容)&lt;/p&gt;
&lt;p&gt;PS:Pyhon解释器与普通文本编辑器前面两步是一毛一样的，仅仅第三步不一样(一个是解释语法，一个是文本展示)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;变量&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.什么是变量&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;量：衡量/记录事物的状态/特征&lt;/p&gt;
&lt;p&gt;变：状态/特征是可以变化的&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.为什么要有变量？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;帮助你记录保存事物的某种状态或特征&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.变量的定义&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1.只能包含数字，字母，下划线&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;2.数字不能开头&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;3.关键字不能作为变量名&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;变量必须先定义后调用(使用)，变量名不要加引号&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4.变量额三要素&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1. id():返回的是一串数字&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;2. type():返回的是该变量对应的主句的类型&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;3. value:该变量指向的内存当中数据的值&lt;/p&gt;
&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>【Python】计算机组成原理/编程语言</title>
      <link>https://zhong-er.com/posts/python%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/</link>
      <pubDate>Thu, 27 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://zhong-er.com/posts/python%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Python学前准备课(计算机组成原理_编程语言).png&#34; loading=&#34;lazy&#34; src=&#34;https://zhong-er.com/assets/201908067099_3043_1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python是一门编程语言 &amp;raquo;&amp;gt;转到&lt;/strong&gt;&lt;a href=&#34;https://mubu.com/doc/17ZnX4ax0a&#34; title=&#34;思维导图&#34;&gt;&lt;strong&gt;思维导图&lt;/strong&gt;****&lt;/a&gt;** &amp;raquo;&amp;gt;转到**&lt;a href=&#34;https://www.cnblogs.com/renvip/p/11098821.html&#34; title=&#34;博客园&#34;&gt;&lt;strong&gt;博客园&lt;/strong&gt;****&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;编程&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.&lt;em&gt;&lt;strong&gt;什么是编程&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;编写程序，谁来编写，人来编写。&lt;/p&gt;
&lt;p&gt;将自己的思维逻辑和想法通过计算机能够识别的语言写下，告诉计算机按照你的思维逻辑去帮你干活。&lt;/p&gt;
&lt;p&gt;编程的最终结果就是一丢文件。&lt;/p&gt;
&lt;p&gt;2.&lt;em&gt;&lt;strong&gt;为什么要编程&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;让计算机能够按照你的思维逻辑去工作，解放人力！！！&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;语言&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;汉语，日语，英语，法语，德育&lt;/p&gt;
&lt;p&gt;事物与事物之间沟通交流的媒介&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;操作系统：（windows,linux,unix&amp;hellip;）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.操作系统是帮你操作计算机硬件的，它帮你封装好了一系列操作硬件的方法。&lt;/p&gt;
&lt;p&gt;2.程序员只需要按照操作系统提供的操作方法即可简介操作硬件。&lt;/p&gt;
&lt;p&gt;3.一套完整的计算机系统由一下三部分组成&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1.应用程序&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;2.操作系统（中间人）&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;3.计算机硬件&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ps:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1.程序员开发的程序都叫做应用程序。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;2.操作系统也是应用程序,但是它针对的是计算机硬件。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;操作系统也是一款应用软件，但是它是针对计算机硬件的，将复杂丑陋的操作封装起来，暴露给用户简单快捷的操作接口，帮助你协调，管理，调度计算机各个硬件。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;计算机五大组成部分&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.&lt;strong&gt;&lt;em&gt;控制器&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2.&lt;strong&gt;&lt;em&gt;运算器&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;控制器+运算器=计算机中央处理器（CPU）&lt;/p&gt;
&lt;p&gt;3.&lt;strong&gt;&lt;em&gt;存储器&lt;/em&gt;&lt;/strong&gt; ：计算机存储系统&lt;/p&gt;
&lt;p&gt;内存&lt;/p&gt;
&lt;p&gt;基于电工作的，通电数据正常读取，一旦断电数据即可丢失。&lt;/p&gt;
&lt;p&gt;优点：读取速度快&lt;/p&gt;
&lt;p&gt;缺点：断电数据丢失&lt;/p&gt;
&lt;p&gt;外存&lt;/p&gt;
&lt;p&gt;优点：能够永久保存数据&lt;/p&gt;
&lt;p&gt;缺点：读取速度慢&lt;/p&gt;
&lt;p&gt;4.&lt;strong&gt;&lt;em&gt;输入设备&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;键盘，鼠标，触摸屏&lt;/p&gt;
&lt;p&gt;5.&lt;strong&gt;&lt;em&gt;输出设备&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;显示器，音响，打印机&lt;/p&gt;
&lt;p&gt;ps:&lt;/p&gt;
&lt;p&gt;输入设备也称input&lt;/p&gt;
&lt;p&gt;输出设备也称output&lt;/p&gt;
&lt;p&gt;存储器也可以叫着IO设备&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;计算机三大核心组件&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.&lt;strong&gt;&lt;em&gt;CPU&lt;/em&gt;&lt;/strong&gt; ：大脑&lt;/p&gt;
&lt;p&gt;2.&lt;strong&gt;&lt;em&gt;内存&lt;/em&gt;&lt;/strong&gt; ：短期记忆&lt;/p&gt;
&lt;p&gt;3.&lt;strong&gt;&lt;em&gt;硬盘&lt;/em&gt;&lt;/strong&gt; ：永远不会消失的本子&lt;/p&gt;
&lt;p&gt;计算机是基于电工作的，而电信号只有高低电频两种状态0和1，计算机里面存储的都是0101的二进制数据。&lt;/p&gt;
&lt;p&gt;CPU工作流程：选取内存中读取命令，将命令解析翻译成自己能够对应上的操作步骤，控制硬件执命令。&lt;/p&gt;
&lt;p&gt;简单指令集&lt;/p&gt;
&lt;p&gt;复杂指令集&lt;/p&gt;
&lt;p&gt;x86架构&lt;/p&gt;
&lt;p&gt;CPU到内存中获取数据最多读32位&lt;/p&gt;
&lt;p&gt;64位 32位&lt;/p&gt;
&lt;p&gt;64位向下兼容32位的软件&lt;/p&gt;
&lt;p&gt;而32位不能够兼容64的软件&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;存储器&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;寄存器&lt;/strong&gt;&lt;/em&gt; ：cpu下一步即将要用到的数据（容量小）&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;高速缓存&lt;/strong&gt;&lt;/em&gt; ：将经常需要用到的容量比较小的数据存储在高速缓存&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;内存&lt;/strong&gt;&lt;/em&gt; ：cpu获取数据的主力还是内存&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
