若尘

若尘 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

若尘 发布了文章 · 3月6日

Python 包管理

1. 模块

  • 一个模块就是一个包含python代码的文件,后缀名称是.py就可以,模块就是个python文件
  • 为什么我们用模块

    • 程序太大,编写维护非常不方便,需要拆分
    • 模块可以增加代码重复利用的方法
    • 当作命名空间使用,避免命名冲突
  • 如何定义模块

    • 模块就是一个普通文件,所以任何代码可以直接书写
    • 不过根据模块的规范,最好在本块中编写以下内容

      - 函数(单一功能)
      - 类(相似功能的组合,或者类似业务模块)
      - 测试代码
      
  • 如何使用模块

    • 模块直接导入

      - 模块名称直接以数字开头,需要借助importlib帮助
    • 语法

      import module_name
      module_name.function_name
      module_name.class_name
    • 案例 01.py,02.py,p01.py,p02.py

          # 案例 01.py
          # 包含一个学生类
          # 一个sayHello函数
          # 一个打印语句
      
          class Student():
              def __init__(self, name = "NoName", age = 18):
                  self.name = name
                  self.age = age
          
              def say(self):
                      print("My name is {0}".format(self.name))
          
          def sayHello():
              print("Hi, ")
          
          print("我是模块p0")
          
          # 案例 02.py
          # 借助于importlib包可以实现导入以数字开头的模块名称
          import importlib
          
          # 相当于导入了一个叫01的模块并把导入模块赋值给了a
          
          a = importlib.import_module("01")
          stu = a.Student()
          stu.say()
          # 案例 p01.py
          # 包含一个学生类
          # 一个sayHello函数
          # 一个打印语句
          
          class Student():
              def __init__(self, name = "NoName", age = 18):
                  self.name = name
                  self.age = age
          
              def say(self):
                      print("My name is {0}".format(self.name))
          
          def sayHello():
              print("Hi, ")
          
          # 此判断语句建议一直作为程序的入口
          if __name__ == '__main__':
              print("我是模块p01")
          # 案例 p02.py
          import p01
          
          stu = p01.Student("xiaojing", 19)
          
          stu.say()
          
          p01.sayHello()
          My name is xiaojing
          Hi, 
    • import 模块 as 别名

      - 导入的同时给模块起一个别名
      - 其余用法跟第一种相同
      - 案例 p03.py
      
          # 案例 p03.py
          import p01 as p
          
          stu = p.Student("yueyue", 18)
          stu.say()
          My name is yueyue
    • from module_name import func_name, class_name

      - 按上述方法有选择性的导入
      - 使用的时候可以直接使用导入的内容,不需要前缀
      - 案例 p04
      
          # 案例 p04.py
          from p01 import Student, sayHello
          
          stu = Student()
          
          stu.say()
          
          sayHello()
        My name is NoName
        Hi,    
    • from module_name import *

      - 导入模块所有内容
      - 案例 p05.py
      
             # 案例 p05.py
          from p01 import *
          
          sayHello()
          
          stu = Student("yaona", 20)
          stu.say()
          Hi, 
          My name is yaona
  • if __name__ == `__main__` 的使用

    • 可以有效的避免模块代码被导入的时候被动执行的问题
    • 建议所有程序的入口都以此代码为入口

2. 模块的搜索路径和存储

  • 什么是模块的搜索路径

    • 加载模块的时候,系统会在哪些地方寻找此模块
  • 系统默认的模块搜索路径

    import sys
    sys.path  属性可以获取路径列表
    # 案例 p06.py
    
        # 案例 p06.py
        import sys
        
        print(type(sys.path))
        print(sys.path)
        
        for p in sys.path:
            print(p)
            <class 'list'>
        ['D:\\python\\project\\包管理', 'D:\\PyCharm Community Edition 2019.1.1\\helpers\\pydev', 'D:\\python\\project', 'D:\\PyCharm Community Edition 2019.1.1\\helpers\\third_party\\thriftpy', 'D:\\PyCharm Community Edition 2019.1.1\\helpers\\pydev', 'C:\\Users\\user\\.PyCharmCE2019.1\\system\\cythonExtensions', 'D:\\python\\project\\包管理', 'D:\\Anaconda3\\envs\\opp\\python37.zip', 'D:\\Anaconda3\\envs\\opp\\DLLs', 'D:\\Anaconda3\\envs\\opp\\lib', 'D:\\Anaconda3\\envs\\opp', 'D:\\Anaconda3\\envs\\opp\\lib\\site-packages']
        D:\python\project\包管理
        D:\PyCharm Community Edition 2019.1.1\helpers\pydev
        D:\python\project
        D:\PyCharm Community Edition 2019.1.1\helpers\third_party\thriftpy
        D:\PyCharm Community Edition 2019.1.1\helpers\pydev
        C:\Users\user\.PyCharmCE2019.1\system\cythonExtensions
        D:\python\project\包管理
        D:\Anaconda3\envs\opp\python37.zip
        D:\Anaconda3\envs\opp\DLLs    
        D:\Anaconda3\envs\opp\lib
        D:\Anaconda3\envs\opp
        D:\Anaconda3\envs\opp\lib\site-packages
    
  • 添加搜索路径

    sys.path.append(dir)
  • 模块的加载顺序

    1. 搜索内存中已经加载好的模块
    2. 搜索python的内置模块
    3. 搜索sys.path路径

  • 包是一种组织管理代码的方式,包里面存放的是模块
  • 用于将模块包含在一起的文件夹就是包
  • 自定义包的结构
    |---包
    |---|---  __init__.py  包的标志文件
    |---|---  模块1
    |---|---  模块2
    |---|---  子包(子文件夹)
    |---|---|---  __init__.py
    |---|---|---  子包模块1
    |---|---|---  子包模块2
    
  • 包的导入操作

    • import package_name

      • 直接导入一个包,可以使用__init__.py中的内容
      • 使用方式是:

        package_name.func_name
        package_name.class_name.func_name()

      • 此种方式的访问内容是
      • 案例 pkg01, p07.py
        # pkg01.__init__py
        def inInit():
            print("I am in init of package")
    
        # pkg01.p01.py
        class Student():
            def __init__(self, name = "NoName", age = 18):
                self.name = name
                self.age = age
        
            def say(self):
                    print("My name is {0}".format(self.name))
        
            def sayHello():
                print("Hi, ")
    
    
        print("我是模块p01")
        # 案例 p07.py
        import pkg01
        
        pkg01.inInit()
        I am in init of package
    
    • import package_name as p

      • 具体用法跟作用方式,跟上述简单导入一致
      • 注意的是此种方法是默认对__init__.py内容的导入
    • import package.module

      • 导入包中某一个具体的模块
      • 使用方法

            package.module.func_name
            package.module.class.fun()
            package.module.class.var
      • 案例 p08.py
        # 案例 p08.py
        import pkg01.p01
        
        stu = pkg01.p01.Student()
        stu.say()
        我是模块p01
        My name is NoName
    
    • import package.module as pm
  • from ... import 导入

    • from package import module1, module2, module3, ... ...
    • 此种导入方法不执行 __init__ 的内容

      from pkg01 import p01
      p01.sayHello()
    • from package import *

      • 导入当前包 __init__.py 文件中所有的函数和类
      • 使用方法

        func_name()
        class_name.func_name()
        class_name.var

      • 案例 p09.py, 注意此种导入的具体内容
        # 案例 p09.py
        from pkg01 import *
        
        inInit()
        
        stu = Student() 
        I am in init of package
        
        NameError: name 'Student' is not defined
  • from package.module import *

    • 导入包中指定的模块的所有内容
    • 使用方法

      func_name()
      class_name.func_name()

  • 在开发环境中经常会引用其他模块,可以在当前包中直接导入其他模块中的内容

    • import 完整的包或者模块的路径
  • __all__ 的用法

    • 在使用from package import 的时候, 可以导入的内容
    • __init__.py 中如果文件为空,或者没有 __all__, 那么只可以把 __init__ 中的内容导入
    • __init__ 如果设置了 __all__ 的值,那么则按照 __all__ 指定的子包或者模块进行加载

    如此则不会载入 __init__ 中的内容

    • __all__=['module1', 'module2', 'package1'... ...]
    • 案例 pkg02,p10.py
        # pkg02.__init__.py
        __all__=['p01']
        
        def inInit():
            print("T am in init of package")
    
        # pkg02.p01.py
        class Student():
            def __init__(self, name = "NoName", age = 18):
                self.name = name
                self.age = age
    
            def say(self):
                print("My name is {0}".format(self.name))
        
            def sayHello():
                print("Hi, ")
        
        # 此判断语句建议一直作为程序的入口
        if __name__ == '__main__':
            print("我是模块p01")
        # 案例 p10.py
        from pkg02 import *
        
        stu = p01.Student()
        stu.say()
    My name is NoName

命名空间

  • 用于区分不同位置不同功能但相同名称的函数或者变量的一个特定前缀
  • 作用是防止命名冲突

    setName()
    Student.setName()
    Dog.setName()

查看原文

赞 0 收藏 0 评论 0

若尘 发布了文章 · 3月4日

Python OOP-5

12. 所用软件

  • 画图软件:Faststone capture

13. 抽象类

  • 抽象方法:没有具体实现内容的方法称为抽象方法
  • 抽象方法的主要意义是规范了子类的行为和接口
  • 抽象的使用需要借助abc模块

    import abc
    
  • 抽象类:包含抽象方法的类叫做抽象类,通常成为ABC类
  • 抽象类的使用

    • 抽象类可以包含抽象方法,也可以包含具体方法
    • 抽象类中可以有方法也可以有属性
    • 抽象类不允许直接实例化
    • 必须继承才可以使用,且继承的子类必须实现所有继承来的抽象方法
    • 假定子类没有实现所有继承的抽象方法,子类也不能实例化
    • 抽象类的主要作用是设定类的标准,以便于开发的时候具有统一的规范

14. 自定义类

  • 类其实是一个类定义和各种方法的自由组合
  • 可以定义类和函数,然后自己通过类来直接赋值
  • 可以借助于MethodType实现
  • 借助于type实现
  • 利用元类实现- MetaClass

    • 元类是类
    • 被用来创造别的类
# 变量的三种用法

class A():
    def __init__(self):
        self.name = "haha"
        self.age = 18
        
a = A()
# 属性的三种用法
# 1. 赋值
# 2. 读取
# 3. 删除
a.name = "ruochen"
print(a.name)
del a.name
# print(a.name)
ruochen


# 类属性 property
# 应用场景:
# 对变量除了普通的三种操作,还想增加一些附加的操作,那么可以通过property完成
class A():
    def __init__(self):
        self.name = "haha"
        self.age = 18
    # 此功能,是对类变量读取操作的时候应该执行的函数功能
    def fget(self):
        print("我被读取了")
        return self.name
    # 模拟的是对变量进行写操作的时候执行的功能
    def fset(self, name):
        print("我被写入了,但是还可以做好多事情")
        self.name = name + "1"
     # fdel模拟的是删除变量的时候进行的操作   
    def fdel(self):
        pass
    
    # property的四个参数顺序的固定的
    # 第一个参数代表读取的时候需要调用的函数
    # 第二个参数代表写入的时候需要调用的函数
    # 第三个是删除
    name2 = property(fget, fset, fdel, "这是一个property的例子")
    
a = A()
print(a.name)

print(a.name2)
haha
我被读取了
haha


# 抽象

class Animel():
    
    def sayHello(self):
        pass
    
class Dog(Animel):
    
    def sayHello(self):
        print("问一下对方")

class Person(Animel):
    
    def sayHello(self):
        print("Kiss me")
        
d = Dog()
d.sayHello()

p = Person()
p.sayHello()
问一下对方
Kiss me


# 抽象类的实现

import abc

# 声明一个类并且指定当前类的元类
class Hunam(metaclass=abc.ABCMeta):
    
    # 定义一个抽象的方法
    @abc.abstractmethod
    def smoking(self):
        pass
    
    # 定义类抽象方法
    @abc.abstractclassmethod
    def drink():
        pass
    
    # 定义静态抽象方法
    @abc.abstractstaticmethod
    def play():
        pass
    
    def sleep(self):
        print("Sleeping......")
# 函数名可以当变量使用

def sayHello(name):
    print("{}你好".format(name))

sayHello("A")

liumang = sayHello

liumang("A")
A你好
A你好


# 自己组装一个类

class A():
    pass

def say(self):
    print("Saying... ...")
    
class B():
    def say(self):
        print("Saying... ...")
        
say(9)

A.say = say

a = A()
a.say()

b = B()
b.say()
Saying... ...
Saying... ...
Saying... ...


# 组装类例子 2
# 自己组装一个类
from types import MethodType
class A():
    pass

def say(self):
    print("Saying... ...")
    
a = A()
a.say = MethodType(say, A)
a.say()
Saying... ...


help(MethodType)
Help on class method in module builtins:

class method(object)
 |  method(function, instance)
 |  
 |  Create a bound instance method object.
 |  
 |  Methods defined here:
 |  
 |  __call__(self, /, *args, **kwargs)
 |      Call self as a function.
 |  
 |  __delattr__(self, name, /)
 |      Implement delattr(self, name).
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __get__(self, instance, owner, /)
 |      Return an attribute of instance, which is of type owner.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __hash__(self, /)
 |      Return hash(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __reduce__(...)
 |      Helper for pickle.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __setattr__(self, name, value, /)
 |      Implement setattr(self, name, value).
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __func__
 |      the function (or other callable) implementing a method
 |  
 |  __self__
 |      the instance to which a method is bound



type(8)
int



# 利用type造一个类

# 先定义类应该具有的成员函数
def say(self):
    print("Saying... ...")
    
def talk(self):
    print("Talking... ...")
    
# 利用type来创建一个类
A = type("AName", (object, ), {"class_say":say, "class_talk":talk})

# 然后可以像正常一样使用类
a = A()
dir(a)
a.class_say()
Saying... ...


# 元类演示

# 元类写法是固定的,他必须继承于type
# 元类一般命名以MetaClass结尾
class CMetaClass(type):
    # 注意以下写法
    def __new__(cls, name, bases, attrs):
        # 自己的业务处理
        print("我是元类")
        attrs['id'] = '000000'
        attrs['addr'] = "1"
        return type.__new__(cls, name, bases, attrs)
    
# 元类定义完就可以使用,使用注意写法
class Teacher(object, metaclass=CMetaClass):
    pass

t = Teacher()

t.__dict__
t.id
我是元类





'000000'


查看原文

赞 0 收藏 0 评论 0

若尘 发布了文章 · 3月3日

Python OOP-4

8. 类的成员描述符(属性)

  • 类的成员描述是为了在类中对类的成员属性进行相关操作而创建的一种方式

    • get:获取属性的操作
    • set:修改或添加属性操作
    • delete:删除属性的操作
  • 如果想使用类的额成员描述符,大概有三种方法

    • 使用类实现描述器
    • 使用属性修饰符
    • 使用property函数

      • property函数很简单
      • property(fget, fset, fdel, doc)
  • 无论哪种修饰符都是为了对成员属性进行相应的控制

    • 类的方式:适用多个类中的多个属性共用同一个描述符
    • property:适用当前类中使用,可以控制一个类中多个属性
    • 属性修饰符:适用于当前类中使用,控制一个类中的一个属性

9. 类的内置属性

    __dict__: 以字典的方式显示类的成员组成
    __doc__: 获取类的文档信息
    __name__: 获取类的名称,如果在模块中使用,获取模块的名称
    __bases__: 获取某个类的所有父类,以元组的方式显示
    

10. 类的常用魔术方法

  • 魔术方法就是不需要人为调用的方法,基本是在特定的时间自动触发
  • 魔术方法的统一特征,方法名被前后各两个下划线包裹
  • 操作类

    • __init__:构造函数
    • __new__:对象实例化方法,此魔术方法较特殊,一般不需要使用
    • __call__:对象当函数使用的时候触发
    • __str__:当对象被当作字符串使用的时候
    • __repr__:返回字符串
  • 描述符相关

    • __set__
    • __get__
    • __delete__
  • 属性操作相关

    • __getattr__:访问一个不存在的属性时触发
    • __setattr__:对成员属性进行设置的时候触发

      • 参数:

        • self用来获取当前对象
        • 被设置的属性名称,以字符串形式出现
        • 需要对属性名称设置的值
      • 作用:进行属性设置的时候进行验证或者修改
      • 注意:在该方法中不能对属性进行赋值操作,否则死循环
  • 运算类相关魔术方法

    • __gt__:进行大于判断的时候触发的函数

      • 参数

        • self
        • 第二个参数是第二个对象
        • 返回值可以是任意值,推荐返回布尔值

11. 类和对象的三种方法

  • 实例方法

    • 需要实例化对象才能使用的方法,使用过程中可能需要截至对象的其他对象的方法完成
  • 静态方法

    • 不需要实例化,通过类直接访问
  • 类方法

    • 不需要实例化
# 属性案例
# 创建Student类,描述学生类
# 学生具有Student.name属性
# 但name格式并不统一
# 可以用增加一个函数,然后自动调用的方式,但很蠢
class Student():
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
        # 如果不想修改代码
        self.setName(name)
        
    # 介绍下自己
    def intro(self):
        print("Hai, my name is {0}".format(self.name))
        
    def setName(self, name):
        self.name = name.upper()
        
s1 = Student("RUO Chen", 19.8)
s2 = Student("michi stangle", 24.0)
s1.intro()
s2.intro()
Hai, my name is RUO CHEN
Hai, my name is MICHI STANGLE


# propertya 案例
# 定义一个Person类,具有name,age属性
# 对于任意输入的姓名,我们希望用大写方式保存
# 年龄,我们希望内部统一用整数保存
# x = property(fget, fset, fdel, doc)
class Person():
    '''
    这是一个人,一个高尚的人,一个脱离了低俗趣味的人
    他还他妈的有属性
    '''
    # 函数名称可以任意
    def fget(self):
        return self._name * 2
    
    def fset(self, name):
        # 所有输入的姓名以大写方式 保存
        self.name = name.upper()
    def fdel(self):
        self._name = "NoName"
        
    name = property(fget, fset, fdel, "对name进行操作")
# 类的内置属性举例
print(Person.__dict__)
print(Person.__doc__)
print(Person.__name__)
# 元组形式显示所有的父类
print(Person.__bases__) 
{'__module__': '__main__', '__doc__': '\n    这是一个人,一个高尚的人,一个脱离了低俗趣味的人\n    他还他妈的有属性\n    ', 'fget': <function Person.fget at 0x000001FBBD3AFBF8>, 'fset': <function Person.fset at 0x000001FBBD3AF9D8>, 'fdel': <function Person.fdel at 0x000001FBBD3AF8C8>, 'name': <property object at 0x000001FBBD3B7BD8>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>}

    这是一个人,一个高尚的人,一个脱离了低俗趣味的人
    他还他妈的有属性
    
Person
(<class 'object'>,)


# init 举例
class A():
    def __init__(self, name = 0):
        print("哈哈,我被调用了")
        
a = A()
哈哈,我被调用了


# __call__ 举例
class A():
    def __init__(self, name = 0):
        print("哈哈,我被调用了")
        
    def __call__(self):
        print("我被调用again")
        
a = A()
a()
哈哈,我被调用了
我被调用again


# __str__ 举例
class A():
    def __init__(self, name = 0):
        print("哈哈,我被调用了")
        
    def __call__(self):
        print("我被调用again")
        
    def __str__(self):
        return '666'
        
a = A()
print(a)
哈哈,我被调用了
666


# __getattr__
class A():
    name = "NoName"
    age = 18
    
    def __getattr__(self, name):
        print("没找到")
        print(name)
    

        
a = A()
print(a.name)
print(a.addr)
NoName
没找到
addr
None


# __setattr__ 案例
class Person():
    def __init__(self):
        pass
    
    def __setattr__(self, name, value):
        print("设置属性:{0}".format(name))
        # 下面语句会导致问题,死循环
        # self.name = value
        # 此种情况,为了避免死循环,规定统一调用父类魔法函数
        super().__setattr__(name, value)
p = Person()
print(p.__dict__)
p.age = 18
{}
设置属性:age


# __gt__

class Student():
    def __init__(self, name):
        self._name = name
        
    def __gt__(self, obj):
        print("哈哈,{0} 会比 {1} 大吗?".format(self, obj))
        return self._name > obj._name
    
stu1 = Student("one")
stu2 = Student("two")
print(stu1 > stu2)
哈哈,<__main__.Student object at 0x000001C15772EB38> 会比 <__main__.Student object at 0x000001C15772E550> 大吗?
False


# 三种方法的案例
class Person():
    # 实例方法
    def eat(self):
        print(self)
        print("Eating......")
    # 类方法
    # 类方法的第一个参数,一般命名为cls,区别于self
    @classmethod
    def play(cls):
        print(cls)
        print("Playing......")
        
    # 静态方法
    # 不需要用第一个参数表示自身或者类
    @staticmethod
    def say():
        print("Saying......")
        
yueyue = Person()

# 实例方法
yueyue.eat()
# 类方法
Person.play()
yueyue.play()
# 静态方法
Person.say()
yueyue.say()
<__main__.Person object at 0x000001C157766710>
Eating......
<class '__main__.Person'>
Playing......
<class '__main__.Person'>
Playing......
Saying......
Saying......

查看原文

赞 0 收藏 0 评论 0

若尘 发布了文章 · 3月2日

Python OOP-3

6.3 多态

  • 多态就是同一个对象在不同情况下有不同的状态出现
  • 多态不是语法,是一种设计思想
  • 多态性:一种调用方式,不同的执行效果
  • 多态:同一事物的多种形态,动物分为人类、猪类、狗类
  • 多态和多态性
  • Mixin设计模式

  • 我们使用多继承语法来实现Mixin
  • 使用Mixin实现多继承的时候非常小心

    • 首先他必须表示某一单一功能,而不是某个物品
    • 职责必须单一,如果有多个功能,则写多个Mixin
    • Mixin不能依赖于子类的实现
    • 子类即使没有继承这个Mixin类,也能照样工作,只是缺少了某个功能
  • 优点

    • 使用Mixin可以在不对类进行任何修改的情况下,扩充功能
    • 可以方便的组织和维护不同功能组件的划分
    • 可以根据需要任意调整功能类的组合
    • 可以避免创建很多新的类,导致类的继承混乱

7. 类相关函数

  • issubclass:检测一个类是否是另一个类的子类
  • isinstance:检测一个对象是否是一个类的实例
  • hasattr:检测一个对象是否有成员xxx
  • getattr:get attribute
  • setattr:set attribute
  • delattr:delete attribute
  • dir:获取对象的成员列表
class A():
    pass

class B(A):
    pass

class C(B,A):
    pass

print(A.__mro__)
print(B.__mro__)
(<class '__main__.A'>, <class 'object'>)
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)


# 多继承的例子
# 子类可以直接拥有父类的属性和方法,私有属性和方法除外
class Fish():
    def __init__(self, name):
        self.name = name
        
    def swim(self):
        print("I am swimming......")
        
class Bird():
    def __init__(self, name):
        self.name = name
        
    def fly(self):
        print("I am flying.....")
        
class Person():
    def __init__(self, name):
        self.name = name
        
    def worked(self):
        print("Working......")
        
class SuperMan(Person, Bird, Fish):
    def __init__(self, name):
        self.name = name    
        
s = SuperMan("a")
s.fly()
s.swim()
s.worked()


# 单继承的例子

class Student(Person):
    def __init__(self, name):
        self.name = name
        
stu = Student("a")
stu.worked()
I am flying.....
I am swimming......
Working......
Working......


# 菱形继承问题
class A():
    pass
class B(A):
    pass
class C(A):
    pass

class D(B,C):
    pass
# 构造函数例子

class Person():
    # 对Person类进行实例化的时候
    # 姓名要确定
    # 年龄得确定
    # 地址肯定有
    def __init__(self):
        self.name = "NoName"
        self.age = 18
        self.address = "Studentwhonheim"
        print("In init func")

# 实例化一个人
p = Person() 
In init func


# 构造函数的调用顺序 - 1
# 如果子类没有写构造函数,则自动向上查找,直到找到为止
class A():
    def __init__(self):
        print("A")
class B(A):
    def __init__(self):
        print("B")

class C(B):
    pass

# 此时,首先C的构造函数
# 如果没有,则向上按照MRO顺序查找父类的构造函数,直到找到为止
c = C()
A


# 构造函数的调用顺序 - 2
class A():
    def __init__(self):
        print("A")
class B(A):
    def __init__(self, name):
        print("B")
        print(name)

class C(B):
    pass

# 此时,首先C的构造函数
# 如果没有,则向上按照MRO顺序查找父类的构造函数,直到找到为止
# 此时,会出现参数结构不对应错误
c = C()
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-11-40c74f7fff64> in <module>
     14 # 如果没有,则向上按照MRO顺序查找父类的构造函数,直到找到为止
     15 # 此时,会出现参数结构不对应错误
---> 16 c = C()


TypeError: __init__() missing 1 required positional argument: 'name'


# 构造函数的调用顺序 - 3
class A():
    def __init__(self):
        print("A")
class B(A):
    def __init__(self, name):
        print("B")
        print(name)

class C(B):
    # C中想扩展B的构造函数
    # 即调用B的构造函数后再添加一些功能
    # 有两种方法实现
    
    '''
    # 第一种是通过父类名调用
    def __init__(self, name):
        # 首先调用父类构造函数
        B.__init__(self, name)
        # 其次,再增加自己的功能
        print("这是C中附加的功能")
    '''
    
    # 第二种,使用super调用
    def __init__(self, name):
        # 首先调用父类构造函数
        super(C, self).__init__(name)
        # 其次,再增加自己的功能
        print("这是C中附加的功能")

# 此时,首先C的构造函数
# 如果没有,则向上按照MRO顺序查找父类的构造函数,直到找到为止
# 此时,会出现参数结构不对应错误
c = C("我是C")
B
我是C
这是C中附加的功能


# Mixin案例

class Person():
    name = "ruochen"
    age = 18
    
    def eat(self):
        print("EAT......")
        
    def drink(self):
        print("DRINK......")
    
    def sleep():
        print("SLEEP......")

class Teacher(Person):
    def work(self):
        print("Work")
        
class Student(Person):
    def study(self):
        print("Study")
        
class Tutor(Teacher, Student):
    pass

t = Tutor()

print(Tutor.__mro__)
print(t.__dict__)
print(Tutor.__dict__)

print("*" * 20)
class TeacherMixin():
    def work(self):
        print("Work")
        
class StudentMixin():
    def study(self):
        print("Study")
        
class TutorM(Person, TeacherMixin, StudentMixin):
    pass

tt = TutorM()
print(TutorM.__mro__)
print(tt.__dict__)
print(TutorM.__dict__)
(<class '__main__.Tutor'>, <class '__main__.Teacher'>, <class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>)
{}
{'__module__': '__main__', '__doc__': None}
********************
(<class '__main__.TutorM'>, <class '__main__.Person'>, <class '__main__.TeacherMixin'>, <class '__main__.StudentMixin'>, <class 'object'>)
{}
{'__module__': '__main__', '__doc__': None}


# issubclass
class A():
    pass

class B(A):
    pass

class C():
    pass

print(issubclass(B, A))
print(issubclass(C, A))
print(issubclass(C, object))
True
False
True


# isinstance
class A():
    pass

a = A()

print(isinstance(a, A))
print(isinstance(A, A))
True
False


# hasattr
class A():
    name = "NoName"

a = A()
print(hasattr(a, "name"))
print(hasattr(a, "age"))
True
False


# help案例
# 我想知道setattr的具体用法
help(setattr)
Help on built-in function setattr in module builtins:

setattr(obj, name, value, /)
    Sets the named attribute on the given object to the specified value.
    
    setattr(x, 'y', v) is equivalent to ``x.y = v''



# dir 案例
class A():
    pass
# dir(A)
a = A
dir(a)
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__']



查看原文

赞 0 收藏 0 评论 0

若尘 发布了文章 · 3月1日

Python OOP-2

6.2 继承

  • 继承就是一个类可以获得另外一个类中的成员属性和成员方法
  • 作用: 减少代码,增加代码的复用功能,同时可以设置类与类直接的关系
  • 继承与被继承的概念:

    • 被继承的类叫父类,也叫基类,也叫超类
    • 用与继承的类,叫子类,也叫派生类
    • 继承与被继承一定存在一个 is-a 关系
  • 继承的特征

    • 所有的类都继承自object类,即所有的类都是object类的子类
    • 子类一旦继承父类,则可以使用父类中除私有成员外的所有内容
    • 子类继承父类后并没有将父类成员完全赋值到子类中,而是通过引用关系访问调用
    • 子类中可以定义独有的成员属性和方法
    • 子类中定义的成员和父类成员如果相同,则优先使用子类成员
    • 子类如果想扩充父类的方法,可以在定义新方法的同时访问父类成员来进行代码重用

    可以使用 [父类名.父类成员] 的格式来调用父类成员,也可以使用[super().父类成员]的
    格式来调用

  • 继承变量函数的查找顺序问题

    • 优先查找自己的变量
    • 没有则查找父类
    • 构造函数如果本类中没有定义,则自动查找调用父类构造函数
    • 如果本类有定义,则不再继续向上查找
  • 构造函数

    • 是一类特殊的函数,在类进行实例化之前进行调用
    • 如果定义了构造函数,则实例化时使用构造函数,不查找父类构造函数
    • 如果没定义,则自动查找父类构造函数
    • 如果子类没定义,父类的构造函数带参数,则构造对象时的参数应该按父类参数构造
  • super

    • super不是关键字,而是一个类
    • super的作用是获取MRO(MethodResolutionOrder)列表中的第一个类
    • super与父类直接没任何实质性关系,但通过super可以调用到父类
    • super使用两个方法,常见在构造函数中调用父类的构造函数
  • 单继承和多继承

    • 单继承:每个类只能继承一个类
    • 多继承:每个类允许继承多个类
  • 单继承和多继承的优缺点

    • 单继承:

      • 传承有序逻辑清晰语法简单隐患少
      • 功能不能无限扩展,只能在当前唯一的继承链中扩展
    • 多继承:

      • 优点:类的功能扩展方便
      • 缺点:继承关系混乱
  • 菱形继承/钻石继承问题

    • 多个子类继承自同一个父类,这些子类又被同一个类继承,

    于是继承关系图形成一个菱形图谱

    • MRO
    • 关于多继承的MRO

      • MRO就是多继承中,用于保存继承顺序的一个列表
      • python本身采用C3算法来多继承的菱形继承来进行计算的结果
      • MRO列表的计算原则:

        • 子类永远在父类前面
        • 如果多个父类,则根据继承语法中括号内类的书写顺序存放
        • 如果多个类继承了同一个父类,孙子类中只会选取继承语法

        括号中第一个父类的父类

  • 构造函数

    • 在对象进行实例化的时候,系统自动调用的一个函数叫构造函数,通常此函数

    用来对实例化对象进行初始化,顾名

    • 构造函数一定要有,如果没有,则自动向上查找,按照MRO顺序,直到找到为止
# 继承的语法
# 在python中,任何类都有一个共同的父类叫object
class Person():
    name = "NoName"
    age = 18
    __score = 0   # 考试成绩是秘密,只要自己知道
    _petname = "sec"   # 小名,是保护的,子类可以用,但不能公用
    def sleep(self):
        print("Sleeping ... ...")

# 父类写在括号里
class Teacher(Person):
    teacher_id = "9527"
    def make_test(self):
        print("attention")

t = Teacher()
print(t.name)
print(t._petname)

# 私有访问问题
# 公开访问私有变量,报错
# print(t.__score)

t.sleep()
print(t.teacher_id)
t.make_test()

NoName
sec
Sleeping ... ...
9527
attention


# 子类和父类定义同一个名称变量,则优先使用子类本身
class Person():
    name = "NoName"
    age = 18
    __score = 0   # 考试成绩是秘密,只要自己知道
    _petname = "sec"   # 小名,是保护的,子类可以用,但不能公用
    def sleep(self):
        print("Sleeping ... ...")

# 父类写在括号里
class Teacher(Person):
    teacher_id = "9527"
    name = "DaNa"
    def make_test(self):
        print("attention")
        
t = Teacher
print(t.name)
DaNa


# 子类扩充父类功能
# 人有工作的函数,老师也有工作的函数,但老师的工作需要讲课
class Person():
    name = "NoName"
    age = 18
    __score = 0   # 考试成绩是秘密,只要自己知道
    _petname = "sec"   # 小名,是保护的,子类可以用,但不能公用
    def sleep(self):
        print("Sleeping ... ...")
        
    def work(self):
        print("make some money")

# 父类写在括号里
class Teacher(Person):
    teacher_id = "9527"
    name = "DaNa"
    def make_test(self):
        print("attention")
        
    def work(self):
        # 扩充父类的功能只需要调用父类相同的函数
        # Person.work(self)
        # 扩充父类的另一种方法
        # super代表得到父类
        super().work()
        self.make_test()
          
t = Teacher()
t.work()
make some money
attention


# 构造函数的概念

class Dog():
        # __init__就是构造函数
        # 每次实例化的时候,第一个被自动的调用
        # 因为主要工作是进行初始化,所以得名
    def __init__(self):
        print("I am init in dog")

# 实例化的时候,括号内的参数需要跟构造函数参数匹配
kaka = Dog()
I am init in dog


# 继承中的构造函数 - 1

class Animel():
    pass

class PaxingAni(Animel):
    pass

class Dog(PaxingAni):
        # __init__就是构造函数
        # 每次实例化的时候,第一个被自动的调用
        # 因为主要工作是进行初始化,所以得名
    def __init__(self):
        print("I am init in dog")
# 实例化的时候,自动调用了Dog的构造函数      
kaka = Dog()
I am init in dog


# 继承中的构造函数 - 2

class Animel():
    def __init__(self):
        print("Animel")

class PaxingAni(Animel):
    def __init__(self):
        print("Paxing Dongwu")

class Dog(PaxingAni):
        # __init__就是构造函数
        # 每次实例化的时候,第一个被自动的调用
        # 因为主要工作是进行初始化,所以得名
    def __init__(self):
        print("I am init in dog")
# 实例化的时候,自动调用了Dog的构造函数     
# 因为找到了构造函数,则不再查找父类的构造函数
kaka = Dog()

# 猫没有写构造函数
class Cat(PaxingAni):
    pass

# 此时应该自动调用构造函数,因为Cat没有构造函数,所以查找父类构造函数
# 在PaxingAni中查找到了构造函数,则停止向上查找
c = Cat()
I am init in dog
Paxing Dongwu


# 继承中的构造函数 - 3

class Animel():
    def __init__(self):
        print("Animel")

class PaxingAni(Animel):
    def __init__(self, name):
        print("Paxing Dongwu {0}".format(name))

class Dog(PaxingAni):
        # __init__就是构造函数
        # 每次实例化的时候,第一个被自动的调用
        # 因为主要工作是进行初始化,所以得名
    def __init__(self):
        print("I am init in dog")
# 实例化Dog时,查找到Dog的构造函数,参数匹配,不报错      
d = Dog()

class Cat(PaxingAni):
    pass
# 此时,由于Cat没有构造函数,则向上查找
# 因为PaxingAni的构造函数需要两个参数,实例化的时候给了一个,报错
c = Cat()
I am init in dog



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-29-35e195f59e34> in <module>
     22 # 此时,由于Cat没有构造函数,则向上查找
     23 # 因为PaxingAni的构造函数需要两个参数,实例化的时候给了一个,报错
---> 24 c = Cat()


TypeError: __init__() missing 1 required positional argument: 'name'


# 继承中的构造函数 - 4

class Animel():
    def __init__(self):
        print("Animel")

class PaxingAni(Animel):
        pass

class Dog(PaxingAni):
    pass

# 实例化Dog时,查找到Dog的构造函数,参数匹配,不报错      
d = Dog()

class Cat(PaxingAni):
    pass
# 此时,由于Cat没有构造函数,则向上查找
# 因为PaxingAni的构造函数需要两个参数,实例化的时候给了一个,报错
c = Cat()
Animel
Animel


print(type(super))
help(super)
<class 'type'>
Help on class super in module builtins:

class super(object)
 |  super() -> same as super(__class__, <first argument>)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
 |  Typical use to call a cooperative superclass method:
 |  class C(B):
 |      def meth(self, arg):
 |          super().meth(arg)
 |  This works for class methods too:
 |  class C(B):
 |      @classmethod
 |      def cmeth(cls, arg):
 |          super().cmeth(arg)
 |  
 |  Methods defined here:
 |  
 |  __get__(self, instance, owner, /)
 |      Return an attribute of instance, which is of type owner.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __self__
 |      the instance invoking super(); may be None
 |  
 |  __self_class__
 |      the type of the instance invoking super(); may be None
 |  
 |  __thisclass__
 |      the class invoking super()


查看原文

赞 0 收藏 0 评论 0

若尘 发布了文章 · 2月28日

Python OOP-1

0. OOP-Python面向对象

  • Python面向对象
  • 面向对象编程

    • 基础
    • 公有私有
    • 继承
    • 组合,Mixin
  • 魔法函数

    - 魔法函数概述
    - 构造类魔法函数
    - 运算类魔法函数
    

    1. 面向对象概述(ObjectOriented, OO)

    • OOP思想

      • 接触到任意一个任务,首先想到的是任务这个世界的构成,是由模型构成的
    • 几个名词

      • OO:面向对象
      • OOA:面向对象的分析
      • OOD:面向对象的设计
      • OOI:面向对象的实现
      • OOP:面向对象的编程
      • OOA->OOD->OOI:面向对象的实现过程
  • 类和对象的概念

    • 类:抽象名词,代表一个集合,共性的事物
    • 对象:具象的东西,单个个体
    • 类跟对象的关系

      - 一个具象,代表一类事物的某一个个体
      - 一个是抽象,代表的是一大类事物
  • 类中的内容,应该具有两个内容

    • 表明事物的特征。叫做属性(变量)
    • 表明事物功能或动作,称为成员方法(函数)

2. 类的基本实现

  • 类的名字

    • 遵守变量命名的规范
    • 大驼峰(有一个或者多个单词构成,每个单词首字母大写,单词跟单词直接相连)
    • 尽量避开跟系统命名相似的命名
  • 如何声明一个类

    • 必须用class关键字
    • 类由属性和方法构成,其他不允许使用
    • 成员属性定义可以直接使用变量赋值,如果没有值,允许使用None
    • 案例 01.py
  • 实例化类

    变量 = 类名()   # 实例化了一个对象
  • 访问对象成员

    • 使用点操作符

      obj.成员属性名称
      obj.成员方法

  • 可以通过默认内置变量检查类和对象的所有成员

    • 对象所有成员检查

      dict前后各有两个下划线

      obj.__dict__

    • 类所有的成员

      dict前后各有两个下划线

      class_name.__dect__

3. anaconda基本使用

  • anaconda主要是一个虚拟环境管理器
  • 还是一个安装包管理器
  • conda list: 显示anaconda安装的包
  • conda env list:显示anaconda的虚拟环境列表
  • conda create -n xxx python=3.6 :创建python版本为3.6的虚拟环境,名称为xxx

4. 类和对象的成员分析

  • 类和对象都可以存储成员,成员可以归类所有,也可以归对象所有
  • 类存储成员时使用的是与类关联的一个对象
  • 对象存储成员是存储在当前对象中
  • 对象访问一个成员时,如果对象中没有该成员,尝试访问类中的同名成员
    如果对象中有此成员,一定使用对象中的成员
  • 创建对象的时候,类中的成员不会放入对象当中,而是得到一个空对象,没有成员
  • 通过对象对类中成员重新赋值或者通过对象添加成员时,对应成员会保存在对象中,
    而不会修改类成员

5.关于self

  • self在对象的方法中表示当前对象本身,如果通过对象调用一个方法,

那么该对象会自动传入到当前方法的第一个参数中

  • self并不是关键字,只是一个用于接收对象的普通参数,理论上可以用任何一个

普通变量名代替

  • 方法中有self形参的方法成为非绑定类的方法,可以通过对象访问,没有self的

是绑定类的方法,只能通过类访问

  • 使用类访问绑定类的方法时,如果类方法中需要访问当前类的成员,可以通过

__class__成员名来访问

6. 面向对象的三大特性

  • 封装
  • 继承
  • 多态

6.1 封装

  • 封装就是对对象的成员进行访问限制
  • 封装的三个级别

    • 公开:public
    • 受保护的:protected
    • 私有的:private
    • public,private,protected不是关键字
  • 判别对象的位置

    • 对象内部
    • 对象外部
    • 子类中
  • python中下划线的使用
  • 私有

    • 私有成员是最高级别的封装,只能在当前类或对象中访问
    • 在成员前面添加两个下划线即可

      class Person():

      # name是共有的成员
      name = "ruochen"
      # __age就是私有成员
      __age = 18
    • Python的私有不是真私有,是一种成为name mangling的改名策略

    可以使用对象._classname_attributename访问

  • 受保护的封装 protected

    • 受保护的封装是将对象成员进行一定级别的封装,然后,在类中或者子类

    中都可以访问,但是在外部不可以

    • 封装方法:在成员名称前添加一个下划线即可
  • 公开的,公共的 public

    • 公共的封装实际对成员没有任何操作,任何地方都可以访问
class Student():
    name = "aaa"
    age = 18
    
Student.__dict__

# 实例化
a = Student()
a.__dict__ 
print(a.name)
aaa


class A():
    name = "dana"
    age = 18
    
    # 注意say的写法,参数有一个self
    def say(self):
        self.name = "aaa"
        self.age = 200

# 此案例说明
# 类实例的属性和其对象的实例的属性在不对对象的实例属性赋值的前提下,
# 指向同一变量

# 此时,A称为类实例
print(A.name)
print(A.age)

print("*" * 20)

# id可以鉴别出一个变量是否和另一个变量是同一变量
print(id(A.name))
print(id(A.age))

print("*" * 20)
a = A()

print(a.name)
print(a.age)
print(id(a.name))
print(id(a.age))
dana
18
********************
2245155422024
140717429003616
********************
dana
18
2245155422024
140717429003616


# 此时,A称为类实例
print(A.name)
print(A.age)

print("*" * 20)

# id可以鉴别出一个变量是否和另一个变量是同一变量
print(id(A.name))
print(id(A.age))

print("*" * 20)
a = A()
# 查看A内所有属性
print(A.__dict__)
print(a.__dict__)

a.name = "yaona"
a.age = 16
print(a.__dict__)

print(a.name)
print(a.age)
print(id(a.name))
print(id(a.age))
dana
18
********************
2245155422024
140717429003616
********************
{'__module__': '__main__', 'name': 'dana', 'age': 18, 'say': <function A.say at 0x0000020ABDBC7E18>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
{}
{'name': 'yaona', 'age': 16}
yaona
16
2245155597256
140717429003552


class Student():
    name = "dana"
    age = 18
    
    # 注意say的写法,参数有一个self
    def say(self):
        self.name = "aaa"
        self.age = 200
        print("My name is {0}".format(self.name))
        print("My age is {0}".format(self.age))
        
    def sayAgain(s):
        print("My name is {0}".format(s.name))
        print("My age is {0}".format(s.age))
        
yueyue = Student()
yueyue.say()
yueyue.sayAgain()
My name is aaa
My age is 200
My name is aaa
My age is 200


class Teacher():
    name = "dana"
    age = 19
    
    def say(self):
        self.name = "yaona"
        self.age = 17
        print("My name is {0}".format(self.name))
        # 调用类的成员变量需要用__class__
        print("My age is {0}".format(__class__.age))
        
    def sayAgain():
        print(__class__.name)
        print(__class__.age)
        print("Hello, nice to see you again")
        
t = Teacher()
t.say()
# 调用绑定类函数使用类名
Teacher.sayAgain()
My name is yaona
My age is 19
dana
19
Hello, nice to see you again


# 关于self的案例

class A():
    name = "ruochen"
    age = 18
    
    def __init__(self):
        self.name = "aaaa"
        self.age = 200
        
    def say(self):
        print(self.name)
        print(self.age)
        
class B():
    name = "bbb"
    age = 99
    
a = A()
# 此时,系统会默认把a作为第一个参数传入函数
a.say()

# 此时,self被a替换
A.say(a)
# 同样可以把A作为参数传入
A.say(A)

# 此时,传入的是类实例B,因为B具有name和age属性,所有不会报错
A.say(B)

# 以上代码,利用鸭子模型
aaaa
200
aaaa
200
ruochen
18
bbb
99


# 私有变量案例
class Person():
    # name是共有的成员
    name = "ruochen"
    # __age就是私有成员
    __age = 18
                
p = Person()
# name是公有变量
print(p.name)
# __age是私有变量
# 注意报错信息 
print(p.__age)
ruochen



---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-41-e118b6505697> in <module>
     11 # __age是私有变量
     12 # 注意报错信息
---> 13 print(p.__age)


AttributeError: 'Person' object has no attribute '__age'


# name.mangling 技术
print(Person.__dict__)

p._Person__age = 19
print(p._Person__age)
{'__module__': '__main__', 'name': 'ruochen', '_Person__age': 18, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
19

查看原文

赞 0 收藏 0 评论 0

若尘 发布了文章 · 2月27日

python 内置数据结构list、set、dict、tuple(三)

关于元组的函数

  • 以下看代码
  • 以下函数,对list基本适用
# len:获取元组的长度
t = (1,2,3,4,5)
len(t)
5



# max,min:最大最小值
print(max(t))
print(min(t))
5
1


# tuple:转化或创建元组
l = (1,2,3,4,5)
t = tuple(l)
print(t)

t = tuple()
print(t)
(1, 2, 3, 4, 5)
()

元组的函数

  • 基本跟list通用
# count:计算指定数据出现的次数
t = (2,1,2,3,45,1,1,2,)

print(t.count(2))

# index:求指定元素在元组中的索引位置

print(t.index(45))
# 如果需要的查找的数字是多个,则返回第一个

print(t.index(1))
3
4
1

元组变量交换法

  • 两个变量交换值
# 两个变量交换值
a = 1
b = 3

print(a)
print(b)
print("*" * 20)
# java程序员会这么写:
c = a
a = b
b = c
print(a)
print(b)

print("*" * 20)
# python写法
a,b = b,a
print(a)
print(b)
1
3
********************
3
1
********************
1
3

集合-set

  • 集合是高中数学中的一个概念
  • 一堆确定的无序的唯一的数据,集合中每一个数据成为一个元素
# 集合的定义
s = set()
print(type(s))
print(s)

# 此时,大括号内一定要有值,否则定义出的是一个dict
s = {1,2,3,4,5,6,7}
print(type(s))
print(s)
<class 'set'>
set()
<class 'set'>
{1, 2, 3, 4, 5, 6, 7}


# 如果只是用大括号定义,则定义的是一个dict类型
d = {}
print(type(d))
print(d)
<class 'dict'>
{}

集合的特征

  • 集合的数据无序,即无法使用索引和分片
  • 集合内部数据元素具有唯一性,可以用来排除重复数据
  • 集合内的数据,str,int,float,tuple,冰冻集合等,即内部只能放置可哈希数据

集合序列操作

# 成员检测
# in,not in
s = {4,5,"i", "love", "you"}
print(s)

if "love" in s:
    print("Yes")
    
if "haha" not in s:
    print("Yes")
{'you', 4, 5, 'love', 'i'}
Yes
Yes

集合遍历操作

# for 循环
s = {4,5,"i", "love", "you"}

for i in s:
    print(i)
you
4
5
love
i


# 带有元组的集合遍历
s = {(1,2,3,), ("i", "love", "you"), (4,5,6)}

for k,m,n in s:
    print(k, "--", m, "--", n)
    
for k in s:
    print(k)
i -- love -- you
4 -- 5 -- 6
1 -- 2 -- 3
('i', 'love', 'you')
(4, 5, 6)
(1, 2, 3)

集合的内涵

# 普通集合内涵
# 以下集合在初始化后自动过滤掉重复元素
s = {23,223,233,2,4,5,6,3,4,1,5,3}
print(s)

# 普通集合内涵
ss = {i for i in s}
print(ss)
{1, 2, 3, 4, 5, 6, 233, 23, 223}
{1, 2, 3, 4, 5, 6, 233, 23, 223}


# 带条件的集合内涵
sss = {i for i in s if i % 2 == 0}
print(sss)
{2, 4, 6}


# 多循环的集合内涵
s1 = {1,2,3,4}
s2 = {"i", "love", "you"}

s = {m*n for m in s2 for n in s1}
print(s)

s = {m*n for m in s2 for n in s1 if n == 2}
print(s)
{'you', 'youyou', 'love', 'lovelovelovelove', 'lovelovelove', 'lovelove', 'iii', 'youyouyouyou', 'ii', 'i', 'iiii', 'youyouyou'}
{'lovelove', 'youyou', 'ii'}

集合函数/关于集合的函数

# len,max,min:跟其他基本的函数一致
s = {23,54,72,3,5,3,3,6,1,543}
print(len(s))
print(max(s))
print(min(s))
8
543
1


# set:生成一个集合
l = {1,2,3,4,5,4,3,2,1}
s = set(l)
print(s)
{1, 2, 3, 4, 5}


# add:向集合内添加元素
s = {1}
s.add(3)
print(s)
{1, 3}


# clear
s = {1,2,3,4,5}
print(id(s))
s.clear()
print(id(s))
# 结果表明clear函数是原地清空数据
1370773843528
1370773843528


# copy:拷贝
# remove:移除指定的值,直接改变原有值,如果要删除的值不存在,报错
# discard:移除集合中指定的值跟remove一样,但是如果要删除的话,不报错
s = {23,4,3,5,1,2,3}
s.remove(4)
print(s)
s.discard(1)
print(s)

print("*" * 20)
s.discard(100)
print(s)

s.remove(100)
print(s)
{1, 2, 3, 5, 23}
{2, 3, 5, 23}
********************
{2, 3, 5, 23}



---------------------------------------------------------------------------

KeyError                                  Traceback (most recent call last)

<ipython-input-35-0113522ad176> in <module>
     12 print(s)
     13 
---> 14 s.remove(100)
     15 print(s)


KeyError: 100


# pop 随机移除一个元素
s = {1,2,3,4,5,6,7}
d = s.pop()
print(d)
print(s)
1
{2, 3, 4, 5, 6, 7}


# 集合函数
# intersection:交集
# difference:差集
# union:并集
# issubset:检查一个集合是否为另一个子集
# issuperset:检查一个集合是否为另一个超集
s1 = {1,2,3,4,5,6}
s2 = {5,6,7,8,9}

s_1 = s1.intersection(s2)
print(s_1)

s_2 = s1.difference(s2)
print(s_2)

s_3 = s1.issubset(s2)
print(s_3)

s_4 = s1.issuperset(s2)
print(s_4)
{5, 6}
{1, 2, 3, 4}
False
False


# 集合数学操作
s1 = {1,2,3,4,5,6}
s2 = {5,6,7,8,9}

# 以下不支持
s_1 = s1 - s2
print(s_1)

s_2 = s1 + s2
print(s_2)
{1, 2, 3, 4}



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-45-fac787d752ea> in <module>
      7 print(s_1)
      8 
----> 9 s_2 = s1 + s2
     10 print(s_2)


TypeError: unsupported operand type(s) for +: 'set' and 'set'

frozen set :冰冻集合

  • 冰冻就是不可以进行任何修改的操作
  • frozenset是一种特殊集合
# 创建
s = frozenset()
print(type(s))
print(s)
<class 'frozenset'>
frozenset()

dict字典

  • 字典是一种组合数据,没有顺序的组合数据,数据以键值对形式出现
# 字典的创建
# 创建空字典1
d = {}
print(type(d))
print(d)

# 创建空字典2
d = dict()
print(d)

# 创建有值的字典,每一组数据用冒号隔开,每一对键值对用逗号隔开
d = {"one":1, "two":2, "three":3}
print(d)

# 用dict创建有内容字典1
d = dict({"one":1, "two":2, "three":3})
print(d)

# 用dict创建有内字典2
# 利用关键参数
d = dict(one=1, two=2, three=3)
print(d)

# 
d = dict( [("one",1), ("two",2), ("three",3)])
print(d)
<class 'dict'>
{}
{}
{'one': 1, 'two': 2, 'three': 3}
{'one': 1, 'two': 2, 'three': 3}
{'one': 1, 'two': 2, 'three': 3}
{'one': 1, 'two': 2, 'three': 3}


字典的特性

  • 字典是序列类型,但是是无序序列,所以没有分片和索引
  • 字典中的数据每个都有键值对组成,即kv对

    • key:必须是可哈希的值,比如:int,string,float,tuple,但是,list,set,dict不行
    • value:任何值

字典常见操作

# 访问数据
d = {"one":1, "two":2, "three":3}
# 注意访问格式
# 中括号内是键值
print(d["one"])

d["one"] = "eins"
print(d)

# 删除某个操作
# 使用del操作
del d["one"]
print(d)
1
{'one': 'eins', 'two': 2, 'three': 3}
{'two': 2, 'three': 3}


# 成员检测:in,not in
# 成员检测检测时的key内容
d = {"one":1, "two":2, "three":3}

if 2 in d:
    print("value")

if "two" in d:
    print("key")
    
if ("two,2") in d:
    print("kv")
key


# 遍历在python2 和 3 中区别比较大,代码不通用
# 按key值使用for循环
d = {"one":1, "two":2, "three":3}
# 使用for循环,直接按keu值访问
for k in d:
    print(k, d[k])
    
# 上述代码可以改写如下
for k in d.keys():
    print(k, d[k])

# 只访问字典的值
for v in d.values():
    print(v)
    
# 注意以下特殊用法
for k,v in d.items():
    print(k, "--", v)
one 1
two 2
three 3
one 1
two 2
three 3
1
2
3
one -- 1
two -- 2
three -- 3

字典生成式

d = {"one":1, "two":2, "three":3}

# 常规字典生成式
dd = {k:v for k,v in d.items()}
print(dd)

# 加限制条件的字典生成式
dd = {k:v for k,v in d.items() if v % 2 == 0}
print(dd)
{'one': 1, 'two': 2, 'three': 3}
{'two': 2}

字典相关函数

# 通用函数:len,max,min,dict
# str(字典):用于返回字典的字符串格式
d = {"one":1, "two":2, "three":3}
print(str(d))
{'one': 1, 'two': 2, 'three': 3}


# clear:清空字典
# items:返回字典的键值对组成的元组格式

d = {"one":1, "two":2, "three":3}
i = d.items()
print(type(i))
print(i)
<class 'dict_items'>
dict_items([('one', 1), ('two', 2), ('three', 3)])


# keys:返回字典的键组成的一个结构
k = d.keys()
print(type(k))
print(k)
<class 'dict_keys'>
dict_keys(['one', 'two', 'three'])


# values:同理,一个可迭代的结构
v = d.values()
print(type(v))
print(v)
<class 'dict_values'>
dict_values([1, 2, 3])


# get:根据指定键返回相应的值,好处是,可以生成默认值

d = {"one":1, "two":2, "three":3}
print(d.get("oner"))

# get默认值是None,可以设置
print(d.get("one", 100))
print(d.get("one33", 100))

print(d['on333'])
None
1
100



---------------------------------------------------------------------------

KeyError                                  Traceback (most recent call last)

<ipython-input-86-f8c01a58018e> in <module>
      8 print(d.get("one33", 100))
      9 
---> 10 print(d['on333'])


KeyError: 'on333'


# fromkeys:使用指定的序列作为键,使用一个值作为字典的所有键的值
l = ["eins", "zwei", "dree"]
# 注意fromkeys两个参数的类型
# 注意fromkeys的调用主体
d = dict.fromkeys(l, "hahahahaha")
print(d)
{'eins': 'hahahahaha', 'zwei': 'hahahahaha', 'dree': 'hahahahaha'}

查看原文

赞 0 收藏 0 评论 0

若尘 发布了文章 · 2月26日

python内置数据结构list、set、dict、tuple(二)

# 传值和传地址的区别
# 对于简单的数值,采用传值操作,即在函数内对参数的操作不影响外面的变量
# 对于复杂变量,采用传地址操作,此时函数内的参数和外部变量是同一份内容,
# 任何地方对此内容的更改都影响另外的变量或参数的使用

def a(n):
    n[2] = 300
    print(n)
    return None

def b(n):
    n += 100
    print(n)
    return None

an = [1,2,3,4,5,6]
bn = 9

print(an)
a(an)
print(an)

print(bn)
b(bn)
print(bn)
[1, 2, 3, 4, 5, 6]
[1, 2, 300, 4, 5, 6]
[1, 2, 300, 4, 5, 6]
9
109
9

关于列表的函数

l = ['a', 'i love you', 45, 766, 5+4j]
l
['a', 'i love you', 45, 766, (5+4j)]



# append 插入一个内容,在末尾追加
a = [i for i in range(1,5)]
print(a)
a.append(100)
print(a)
[1, 2, 3, 4]
[1, 2, 3, 4, 100]


# insert:指定位置插入
# insert(index, date),插入位置是index前面
print(a)
a.insert(3, 666)
print(a)
[1, 2, 3, 4, 100]
[1, 2, 3, 666, 4, 100]


# 删除
# del 删除
# pop,从对应位拿出一个元素,即把最后一个元素取出来
print(a)
last_ele = a.pop()
print(last_ele)
print(a)
[1, 2, 3, 666, 4, 100]
100
[1, 2, 3, 666, 4]


# remove:在列表中删除指定的值的元素
# 如果被删除的值没在list中,则报错
# 即,删除List指定值的操作应该使用try...excepty语句,或者先行进行判断
# if x in list:
#    list.remove(x)
a.insert(4, 666)
print(a)
print(id(a))
a.remove(666)
print(a)
print(id(a))

# 输出两个id值一样,说明,remove操作是在原list直接操作
[1, 2, 3, 4, 666]
2261435601928
[1, 2, 3, 4]
2261435601928


# clear:清空
print(a)
print(id(a))
a.clear()
print(a)
print(id(a))

# 如果不需要列表地址保持不变,则清空列表可以使用以下方式
# a = list[]
# a = [ ]
[]
2261435601928
[]
2261435601928


# reverse:翻转,原地翻转

a = [1,2,3,4,5]
print(a)
print(id(a))

a.reverse()
print(a)
print(id(a))
[1, 2, 3, 4, 5]
2261441839496
[5, 4, 3, 2, 1]
2261441839496


# exrend:扩展列表,两个列表,把一个直接拼接到后一个上

a = [1,2,3,4,5]
b = [6,7,8,9,10]
print(a)
print(id(a))

a.extend(b)
print(a)
print(id(a))
[1, 2, 3, 4, 5]
2261441540872
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
2261441540872


# count:查找列表中指定值或元素的个数
print(a)
a.append(8)
a.insert(4, 8)
print(a)
a_len = a.count(8)
print(a_len)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 8, 5, 6, 7, 8, 9, 10, 8]
3


# copy:拷贝,浅拷贝

# 列表类型变量赋值示例
a = [1,2,3,4,5,666]
print(a)
# list类型,简单赋值操作,是传地址
b = a
b[3] = 777
print(a)
print(id(a))
print(b)
print(id(b))

print("*" * 20)

# 为了解决以上问题,list赋值需要采用copy函数
b = a.copy()
print(a)
print(id(a))
print(b)
print(id(b))

print("*" * 20)
b[3] = 888
print(a)
print(b)
[1, 2, 3, 4, 5, 666]
[1, 2, 3, 777, 5, 666]
2195797555400
[1, 2, 3, 777, 5, 666]
2195797555400
********************
[1, 2, 3, 777, 5, 666]
2195797555400
[1, 2, 3, 777, 5, 666]
2195798283976
********************
[1, 2, 3, 777, 5, 666]
[1, 2, 3, 888, 5, 666]


# 深拷贝跟浅拷贝的区别
# 出现下列问题的原因是,copy函数是个浅拷贝函数,即只拷贝一层内容
# 深拷贝需要使用特定工具
a = [1,2,3, [10 ,20 ,30]]
b = a.copy()
print(id(a))
print(id(b))
print(id(a[3]))
print(id(b[3]))
a[3][2] = 666
print(a)
print(b)
2195798054792
2195796420296
2195798108872
2195798108872
[1, 2, 3, [10, 20, 666]]
[1, 2, 3, [10, 20, 666]]

元组-tuple

  • 元组可以看成是一个不可更改的list

元组创建

# 创建空元组
t = ()
print(type(t))

# 创建一个只有一个值的元组
s = (1)
print(type(s))
print(s)

t = (1, )
print(type(t))
print(t)

t = 1,
print(type(t))
print(t)

# 创建多个值的元组
t = (1,2,3,4,5)
print(type(t))
print(t)

t = 1,2,3,4,5
print(type(t))
print(t)

# 使用其他结构创建
l = [1,2,3,4,5]
t = tuple(l)
print(t)
<class 'tuple'>
<class 'int'>
1
<class 'tuple'>
(1,)
<class 'tuple'>
(1,)
<class 'tuple'>
(1, 2, 3, 4, 5)
<class 'tuple'>
(1, 2, 3, 4, 5)
(1, 2, 3, 4, 5)

元组的特性

  • 是序列表,有序
  • 元组数据值可以访问,不能修改,不能修改,不能修改
  • 元组数据可以是任意类型
  • 总之,list所有特性,除了可修改外,元组都具有
  • 也就意味着,list具有的一些操作,比如索引,分片,序列相加,相乘,成员资格操作等,一模一样
# 索引操作
t = (1,2,3,4,5)
print(t[4])
5


# 超标错误
print(t[12])
---------------------------------------------------------------------------

IndexError                                Traceback (most recent call last)

<ipython-input-22-0db0bf4ec3b5> in <module>
      1 # 超标错误
----> 2 print(t[12])


IndexError: tuple index out of range


t = (1,2,3,4,5,6)
t1 = t[1::2]
print(id(t))
print(id(t1))
print(t1)

# 切片可以超标
t2 = t[2:100]
print(t2)
2195798058760
2195797607552
(2, 4, 6)
(3, 4, 5, 6)


# 序列相加
t1 = (1,2,3)
t2 = (4,5,6,7)

# 传址操作
print(t1)
print(id(t1))
t1 += t2
print(t1)
print(id(t1))

# 以上操作,类似于
t1 = (1,2,3)
t1 = (2,3,4)

# tuple 的不可修改,指的是内容不可修改
# 修改tuple内容会导致报错
t1[1] = 100
(1, 2, 3)
2195798298200
(1, 2, 3, 4, 5, 6, 7)
2195795953560



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-32-e65ebb898657> in <module>
     16 # tuple 的不可修改,指的是内容不可修改
     17 # 修改tuple内容会导致报错
---> 18 t1[1] = 100


TypeError: 'tuple' object does not support item assignment


# 元组相乘
t = (1,2,3)
t = t * 3
print(t)
(1, 2, 3, 1, 2, 3, 1, 2, 3)


# 成员检测
t = (1,2,3)
if 2 in t:
    print("Yes")
else:
    print("No")
Yes


# 元组遍历,一般采用for
# 1. 单层元组遍历
t = (1,2,3,"ruochen", "i", "love")
for i in t:
    print(i, end=" ")
1 2 3 ruochen i love 

# 2. 双层元组的遍历
t = ((1,2,3), (2,3,4), ("i", "love", "you"))

# 对以上元组的遍历,可以如下
# 1.

for i in t:
    print(i)
    
for k,m,n in t:
    print(k, "--", m, "--", n)
(1, 2, 3)
(2, 3, 4)
('i', 'love', 'you')
1 -- 2 -- 3
2 -- 3 -- 4
i -- love -- you

查看原文

赞 0 收藏 0 评论 0

若尘 发布了文章 · 2月25日

python内置数据结构list、set、dict、tuple(一)

汉诺塔问题

  • 规则:

    1. 每次只能移动一个盘子
    2. 任意一次移动,三个塔的状态必须是小盘子在上,大盘子在上
  • 方法:

    1. n=1:直接把A上的一个盘子移动到C上,A->C
    2. n=2:

      1. 把小盘子从A放到B上,A->B
      2. 把大盘子从A放到C上,A->C
      3. 把小盘子从B放到C上,B->C
    3. n=3:

      1. 把A上的两个盘子,通过C移动到B上去,调用递归实现
      2. 把A上剩下的一个最大盘子移动到C上,A->C
      3. 把B上两个盘子,借助于A,挪到C上去,调用递归
    4. n=n:

      1. 把A上的n-1个盘子,借助于C,移动到B上去,调用递归
      2. 把A上的最大盘子,也是唯一一个,移动到C上去,A->C
      3. 把B上n-1个盘子,借助于A,移动到C上去,调用递归
def hano(n, a, b, c):
    '''
    
    汉诺塔的递归实现
    n:代表几个塔
    a:代表第一个塔,开始的塔
    b:代表第二个塔,中间过渡的塔
    c:代表第三个塔,目标塔
    '''
    if n == 1:
        print(a, "-->", c)
        return None
    
    '''
    if n== 2:
        print(a, "-->", b)
        print(a, "-->", c)
        print(b, "-->", c)
        return None
    '''

    # 把n-1个塔,从a塔借助于c塔,挪到b塔上去
    hano(n-1, a, c, b)
    print(a, "-->", c)
    # 把n-1个塔,从b塔,借助于a塔,挪到c塔上去
    hano(n-1, b, a, c)
    
a = 'A'
b = 'B'
c = 'C'

n = 1
hano(n, a, b, c)
    
A --> C


n = 2
hano(n, a, b, c)
A --> B
A --> C
B --> C


n = 3
hano(n, a, b, c)
A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C


n = 5
hano(n, a, b, c)
A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C
A --> B
C --> B
C --> A
B --> A
C --> B
A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C
B --> A
C --> B
C --> A
B --> A
B --> C
A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C

List(列表)

  • del:删除命令
# del 删除
a = [1,2,3,4,5,6]
del a[2]
print(a)
[1, 2, 4, 5, 6]


# del 删除
# 如果使用del之后,id的值和删除前不一样,则说明删除生成了一个新的List
a = [1,2,3,4,5,6]
print(id(a))
del a[2]
print(id(a))
print(a)
1787345100360
1787345100360
[1, 2, 4, 5, 6]


# del一个变量后不能再继续使用此变量
del a
print(a)
---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

<ipython-input-15-a09b634934b2> in <module>
      1 # del一个变量后不能再继续使用此变量
----> 2 del a
      3 print(a)


NameError: name 'a' is not defined

列表相加

# 使用加号连接两个列表
a = [1,2,3,4,5]
b = [5,6,7,8,9]
d = ['a', 'b', 'c']
c = a + b + d
print(c)
[1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 'a', 'b', 'c']


# 使用乘号操作列表
# 列表直接跟一个整数想乘
# 相当于把n个列表接在一起

a = [1,2,3,4,5]
b = a * 3
print(b)
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]


# 成员资格运算
# 就是判断一个元素是否在列表list里边

a = [1,2,3,4,5,6]
b = 8

# c的值是一个布尔值
c = b in a
print(c)

b = 4
print(b in a)
False
True


# not in
a = [1,2,3,4,5]
b = 9

print(b not in a)
True

列表的遍历

  • for
  • while
# for in list
a = [1,2,3,4,5]

# 挨个打印a里边的元素
for i in a:
    print(i)
1
2
3
4
5


# java, c++ 程序员写的python代码是这样的
for i in range(0,len(a)):
    print(a[i])
    i += 1
1
2
3
4
5


b = ["I love you"]

for i in b:
    print(i)
I love you


# range
# in 后面的变量要求是可以迭代的内容
for i in range(1,10):
    print(i)
    
print(type(range(1,10)))
1
2
3
4
5
6
7
8
9
<class 'range'>


# while循环访问list
# 一般不用while遍历list

a = [1,2,3,4,5,6]
length = len(a)
# indx表示的是list的下标
indx = 0
while indx < length:
    print(a[indx])
    indx += 1
1
2
3
4
5
6


# 双层列表循环

# a为嵌套列表,或者叫双层列表
a = [["one", 1], ["two", 2], ["three", 3]]

for k,v in a:
    print(k, "--", v)
one -- 1
two -- 2
three -- 3


# 双层列表循环变异

# a为嵌套列表,或者叫双层列表
a = [["one", 1, "enis"], ["two", 2], ["three", 3,4,5,6,8]]

for k,v in a:
    print(k, "--", v)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-44-db702adbc386> in <module>
      4 a = [["one", 1, "enis"], ["two", 2], ["three", 3,4,5,6,8]]
      5 
----> 6 for k,v in a:
      7     print(k, "--", v)


ValueError: too many values to unpack (expected 2)


# 双层列表循环变异

# a为嵌套列表,或者叫双层列表
a = [["one", 1, "enis"], ["two", 2, "zwei"], ["three", 3, "drei"]]
# 这个例子说明:k,v,w的个数应该跟解包出来的变量个数一致
for k,v,w in a:
    print(k, "--", v, "--", w)
one -- 1 -- enis
two -- 2 -- zwei
three -- 3 -- drei

列表内涵:List content

  • 通过简单的方法创作列表
# for 创建
a = ['a', 'b', 'c']
# 用List a创建一个List b
# 下面的代码的含义是,对于所有a中的元素,逐个放入新列表b中
b = [i for i in a]
print(b)
['a', 'b', 'c']


# 对a中所有元素乘以10,生成一个新List
a = [1, 2, 3, 4, 5]
# 用List a创建一个List b
# 下面的代码的含义是,对于所有a中的元素,逐个放入新列表b中
b = [i*10 for i in a]
print(b)
[10, 20, 30, 40, 50]


# 还可以过滤原来List中的内容并放入新列表
# 比如原有列表,需要把所有a中的偶数生成新的列表b

a = [x for x in range(1,35)]    # 生成从1到34的一个列表
# 把a中所有偶数生成一个新的列表 b
b = [m for m in a if m % 2 == 0]
print(b)
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34]


# 列表生成式可以嵌套
# 有两个列表a,b
a = [i for i in range(1,4)]  # 生成List a
print(a)

b = [i for i in range(100,400) if i % 100 == 0]
print(b)

# 列表生成是可以嵌套,此时等于两个for循环嵌套
c = [m+n for m in a for n in b]
print(c)

# 上面代码跟下面代码等价
for m in a:
    for n in b:
        print(m+n, end=" ")
print()

# 嵌套的列表生成也可以用条件表达式
c = [m+n for m in a for n in b if m+n < 250]
print(c)
[1, 2, 3]
[100, 200, 300]
[101, 201, 301, 102, 202, 302, 103, 203, 303]
101 201 301 102 202 302 103 203 303 
[101, 201, 102, 202, 103, 203]

关于列表的常用函数

# len:求列表长度
a = [x for x in range(1,100)]
print(len(a))

# max:求列表中的最大值
# min:同理
print(max(a))

b = ["man", "film", "python"]
print(max(b))
99
99
python


# List:将其他格式的数据转换成List
a = [1,2,3]
print(list(a))
[1, 2, 3]


s = "I love you"
print(list(s))
['I', ' ', 'l', 'o', 'v', 'e', ' ', 'y', 'o', 'u']


# 把range产生的内容转换成list
print(list(range(12,19)))
[12, 13, 14, 15, 16, 17, 18]

查看原文

赞 0 收藏 0 评论 0

若尘 发布了文章 · 2月24日

python 变量作用域和列表

变量作用域

  • 变量由作用范围限制
  • 分类:按照作用域分类

    • 全局(global):在函数外部定义
    • 局部(local):在函数内部定义
  • 变量的作用范围

    • 全局变量:在整个全局范围都有效
    • 全局变量在局部可以使用(即函数内部可以访问函数外部定义的变量)
    • 局部变量在局部范围可以使用
    • 局部变量在全局范围无法使用
  • LEGB原则

    • L(Local)局部作用域
    • E(Enclosing function local)外部嵌套函数作用域
    • G(Global module)函数定义所在模块作用域
    • B(Buildin):python内置模块的作用域
# 认为a1是全局的
a1 = 100

def fun():
    print(a1)
    print("I am in fun")
    # a2的作用范围是fun
    a2 = 99
    print(a2)
    
print(a1)
fun()
# print(a2)
100
100
I am in fun
99

提升局部变量为全局变量

  • 使用global
  • 案例如下
def fun():
    global b1 
    b1 = 100
    print(b1)
    print("I am in fun")
    b2 = 99
    print(b2)

fun()
print(b1)
100
I am in fun
99
100

global,local函数

  • 可以通过globals和locals显示出局部变量和全局变量
  • 参考一下案例
# globals 和 locals
# globals 和 locals 叫做内建函数
a = 1
b = 2

def fun(c,d):
    e = 111
    print("Locals={0}".format(locals()))
    print("Globals={0}".format(globals()))
          
fun(100, 200)
Locals={'c': 100, 'd': 200, 'e': 111}
Globals={'__name__': '__main__', '__doc__': 'Automatically created module for IPython interactive environment', '__package__': None, '__loader__': None, '__spec__': None, '__builtin__': <module 'builtins' (built-in)>, '__builtins__': <module 'builtins' (built-in)>, '_ih': ['', '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a2)', '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a1)', '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a1)\nfun()\n# print(a2)', '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a1)\nfun()\nprint(a2)', '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a1)\nfun()\n# print(a2)', 'def fun():\n    b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n    \nfun()', 'def fun():\n    global b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n\nprint(b1)', 'def fun():\n    global b1 \n    b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n\nprint(b1)', 'def fun():\n    global b1 \n    b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n\nprint(b1)', 'def fun():\n    global b1 \n    b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n\nprint(b1)', '# globals 和 locals\na = 1\nb = 2\n\ndef fun(c,d):\n    e = 111\n    print("Locals={0}".format(locals()))\n    print("Globals={0}".format(globals())\n          \nfun(100, 200)', '# globals 和 locals\na = 1\nb = 2\n\ndef fun(c,d):\n    e = 111\n    print("Locals={0}".format(locals()))\n    print("Globals={0}".format(globals()))\n          \nfun(100, 200)', '# globals 和 locals\n# globals 和 locals 叫做内建函数\na = 1\nb = 2\n\ndef fun(c,d):\n    e = 111\n    print("Locals={0}".format(locals()))\n    print("Globals={0}".format(globals()))\n          \nfun(100, 200)'], '_oh': {}, '_dh': ['d:\\Jupyter\\nootbook\\笔记'], 'In': ['', '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a2)', '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a1)', '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a1)\nfun()\n# print(a2)', '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a1)\nfun()\nprint(a2)', '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a1)\nfun()\n# print(a2)', 'def fun():\n    b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n    \nfun()', 'def fun():\n    global b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n\nprint(b1)', 'def fun():\n    global b1 \n    b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n\nprint(b1)', 'def fun():\n    global b1 \n    b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n\nprint(b1)', 'def fun():\n    global b1 \n    b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n\nprint(b1)', '# globals 和 locals\na = 1\nb = 2\n\ndef fun(c,d):\n    e = 111\n    print("Locals={0}".format(locals()))\n    print("Globals={0}".format(globals())\n          \nfun(100, 200)', '# globals 和 locals\na = 1\nb = 2\n\ndef fun(c,d):\n    e = 111\n    print("Locals={0}".format(locals()))\n    print("Globals={0}".format(globals()))\n          \nfun(100, 200)', '# globals 和 locals\n# globals 和 locals 叫做内建函数\na = 1\nb = 2\n\ndef fun(c,d):\n    e = 111\n    print("Locals={0}".format(locals()))\n    print("Globals={0}".format(globals()))\n          \nfun(100, 200)'], 'Out': {}, 'get_ipython': <bound method InteractiveShell.get_ipython of <ipykernel.zmqshell.ZMQInteractiveShell object at 0x000001B07AF18BA8>>, 'exit': <IPython.core.autocall.ZMQExitAutocall object at 0x000001B07D7398D0>, 'quit': <IPython.core.autocall.ZMQExitAutocall object at 0x000001B07D7398D0>, '_': '', '__': '', '___': '', '_i': '# globals 和 locals\na = 1\nb = 2\n\ndef fun(c,d):\n    e = 111\n    print("Locals={0}".format(locals()))\n    print("Globals={0}".format(globals()))\n          \nfun(100, 200)', '_ii': '# globals 和 locals\na = 1\nb = 2\n\ndef fun(c,d):\n    e = 111\n    print("Locals={0}".format(locals()))\n    print("Globals={0}".format(globals())\n          \nfun(100, 200)', '_iii': 'def fun():\n    global b1 \n    b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n\nprint(b1)', '_i1': '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a2)', 'a1': 100, 'fun': <function fun at 0x000001B07D8C41E0>, '_i2': '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a1)', '_i3': '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a1)\nfun()\n# print(a2)', '_i4': '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a1)\nfun()\nprint(a2)', '_i5': '# 认为a1是全局的\na1 = 100\n\ndef fun():\n    print(a1)\n    print("I am in fun")\n    a2 = 99\n    print(a2)\n    \nprint(a1)\nfun()\n# print(a2)', '_i6': 'def fun():\n    b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n    \nfun()', '_i7': 'def fun():\n    global b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n\nprint(b1)', '_i8': 'def fun():\n    global b1 \n    b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n\nprint(b1)', '_i9': 'def fun():\n    global b1 \n    b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n\nprint(b1)', '_i10': 'def fun():\n    global b1 \n    b1 = 100\n    print(b1)\n    print("I am in fun")\n    b2 = 99\n    print(b2)\n\nprint(b1)', '_i11': '# globals 和 locals\na = 1\nb = 2\n\ndef fun(c,d):\n    e = 111\n    print("Locals={0}".format(locals()))\n    print("Globals={0}".format(globals())\n          \nfun(100, 200)', '_i12': '# globals 和 locals\na = 1\nb = 2\n\ndef fun(c,d):\n    e = 111\n    print("Locals={0}".format(locals()))\n    print("Globals={0}".format(globals()))\n          \nfun(100, 200)', 'a': 1, 'b': 2, '_i13': '# globals 和 locals\n# globals 和 locals 叫做内建函数\na = 1\nb = 2\n\ndef fun(c,d):\n    e = 111\n    print("Locals={0}".format(locals()))\n    print("Globals={0}".format(globals()))\n          \nfun(100, 200)'}

eval()函数

  • 把一个字符串当成一个表达式来执行,返回表达式执行后的结果
  • 语法:

    eval(string_code, globals=None, locals=None)

exec()函数

  • 跟eval功能类似,但是,不返回结果
  • 语法:

    exec(string_code, globals=None, locals=None)

x = 100
y = 200
# 执行x+y
# z = x + y
z1 = x + y
z2 = eval("x+y")

print(z1)
print(z2)
300
300


# exec案例
x = 100
y = 200
# 执行x+y
# z = x + y
z1 = x + y
# 1. 注意字符串中引号的写法
# 2. 比对exec执行结果和代码执行结果
z2 = exec("print('x+y:',x+y)")

print(z1)
print(z2)
x+y: 300
300
None

递归函数

  • 函数直接或者间接调用自身
  • 优点:简洁,理解容易
  • 缺点:对递归深度有限制,消耗资源大
  • python对递归深度有限制,超过限制报错
  • 在写递归程序的时候,一定注意结束条件
# 递归调用深度限制代码

x = 0
def fun():
    global x
    x += 1
    print(x)
    # 函数自己调用自己
    fun()
    
# 调用函数
# fun()
---------------------------------------------------------------------------

RecursionError                            Traceback (most recent call last)

<ipython-input-23-bfedb7e396bc> in <module>
     10 
     11 # 调用函数
---> 12 fun()


<ipython-input-23-bfedb7e396bc> in fun()
      7     print(x)
      8     # 函数自己调用自己
----> 9     fun()
     10 
     11 # 调用函数


... last 1 frames repeated, from the frame below ...


<ipython-input-23-bfedb7e396bc> in fun()
      7     print(x)
      8     # 函数自己调用自己
----> 9     fun()
     10 
     11 # 调用函数


RecursionError: maximum recursion depth exceeded while calling a Python object


# 斐波那契数列
# 一列数字,第一个值是1,第二个也是1,从第三个开始,每一个数字的值等于前两个数字出现的值的和
# 数学公式为: f(1) = 1, f(2) = 1, f(n) = f(n - 1) + f(n - 2)
# 例如: 1,1,2,3,5,8,13....

# n表示求第n个数字的斐波那契数列的值
def fib(n):
    if n == 1 or n == 2:
        return 1
    elif n > 0:
        return fib(n-1) + fib(n-2)
    else:
        return None

print(fib(3))
print(fib(5))
print(fib(10))
print(fib(-1))
print(fib(1))
2
5
55
None
1

内置数据结构(变量类型)

  • list
  • set
  • dict
  • tuple

list(列表)

  • 一组有顺序的数据的组合
  • 创建列表

    • 空列表
# 1. 创建空列表
l1 = []
# type是内置函数,负责打印出变量的类型
print(type(l1))
print(l1)

# 2. 创建带值的列表
l2 = [100]
print(type(l2))
print(l2)

# 3. 创建列表,带多个值
l3 = [2,3,5,5,9,7,8,]
print(type(l3))
print(l3)

# 4. 使用list()
l4 = list()
print(type(l4))
print(l4)
<class 'list'>
[]
<class 'list'>
[100]
<class 'list'>
[2, 3, 5, 5, 9, 7, 8]
<class 'list'>
[]

列表常用操作

  • 访问

    • 使用下标操作(索引)
    • 列表的位子是从0开始
  • 分片操作

    • 对列表进行任意一段的截取
    • l[:]
# 下标访问列表
l = [3,2,5,1,9,8,7]

print(l[1])
2


print(l[0])
3


# 分片操作
# 注意截取的范围,包含左边的下标值,不包含右边的下标值
print(l[1:4])

# 下标值可以为空,如果不写,左边下标值默认为0,右边下标值为最大数加一,即表示截取到最后一个数据
print(l[:])
print(l[:4])
print(l[2:])
[2, 5, 1]
[3, 2, 5, 1, 9, 8, 7]
[3, 2, 5, 1]
[5, 1, 9, 8, 7]


print(l)
# 分片可以控制增长幅度,默认增长幅度为1
print(l[1:6:1])

# 打印从下标1开始的数字,每次隔一个
print(l[1:6:2])

# 下标可以超出范围,超出后不在考虑多余下标内容
print(l[2:10])

# 下标值,增长幅度可以为负数
# 为负数,表明为从右往左
# 规定: 数组最后一个数字的下标是-1
[3, 2, 5, 1, 9, 8, 7]
[2, 5, 1, 9, 8]
[2, 1, 8]
[5, 1, 9, 8, 7]


# 分片之负数下标
print(l)

# 下面显示的是为空,因为默认分片总是从左向右截取
print(l[-2:-4])
print(l[-4:-2])

# 如果分片一定左边值比右边大,则步长参数需要使用负数
# 此案例为一个list直接正反截取提供了一个思路
print(l[-2:-4:-1])
print(l[-1:-8:-1])
[3, 2, 5, 1, 9, 8, 7]
[]
[1, 9]
[8, 9]
[7, 8, 9, 1, 5, 2, 3]

分片操作是生成一个新的list

  • 内置函数id,负责显示一个变量或者数据的唯一确定编号
# id函数举例
a = 100
b = 200
print(id(a))
print(id(b))

# a跟c指向同一份数据
c = a
print(id(c))

a = 101
print(a)
print(c)

print(id(a))
print(id(c))
140734817148832
140734817152032
140734817148832
101
100
140734817148864
140734817148832


# 通过id可以直接判断出分片是重新生成了一份数据还是使用同一份数据
l = [3,5,6,8,5,43,4,7]
ll = l[:]     # 分片操作
lll = ll
# 如果两个id值一样,则表明分片产生的列表是使用的同一地址同一份数据
# 否则,则表明分片是重新产生了一份数据,即一个新的列表,然后把数据拷贝到新列表中
print(id(l))
print(id(ll))
print(id(lll))

# 通过id知道,ll和lll是同一份数据,验证代码如下
l[1] = 100
print(l)
print(ll)
print(lll)

ll[1] = 100
print(ll)
print(lll)
1857540073800
1857540052488
1857540052488
[3, 100, 6, 8, 5, 43, 4, 7]
[3, 5, 6, 8, 5, 43, 4, 7]
[3, 5, 6, 8, 5, 43, 4, 7]
[3, 100, 6, 8, 5, 43, 4, 7]
[3, 100, 6, 8, 5, 43, 4, 7]


查看原文

赞 0 收藏 0 评论 0

认证与成就

  • 获得 4 次点赞
  • 获得 1 枚徽章 获得 0 枚金徽章, 获得 1 枚银徽章, 获得 0 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2月6日
个人主页被 1.3k 人浏览