python高级知识点


import导入模块

1. import 搜索路径

import sys
sys.path

程序执行时导入模块路径

sys.path.append('/home/itcast/xxx')
sys.path.insert(0, '/home/itcast/xxx')    #可以确保先搜索这个路径
In [37]: sys.path.insert(0,"/home/python/xxxx")
In [38]: sys.path
Out[38]: 
['/home/python/xxxx',
 '',
 '/usr/bin',
 '/usr/lib/python35.zip',
 '/usr/lib/python3.5',
 '/usr/lib/python3.5/plat-x86_64-linux-gnu',
 '/usr/lib/python3.5/lib-dynload',
 '/usr/local/lib/python3.5/dist-packages',
 '/usr/lib/python3/dist-packages',
 '/usr/lib/python3/dist-packages/IPython/extensions',
 '/home/python/.ipython']

2. 重新导入模块

模块被导入后,import module不能重新导入模块,重新导入需用

循环导入

1. 什么是循环导入

a.py

from b import b 

print '---------this is module a.py----------'
def a():
    print("hello, a")
    b() 

a()

b.py

from a import a

print '----------this is module b.py----------'
def b():
    print("hello, b")

def c():
    a() 
c()

2. 怎样避免循环导入

  • 程序设计上分层,降低耦合
  • 导入语句放在后面需要导入时再导入,例如放在函数体内导入

    作用域

    什么是命名空间

    比如有一个学校,有10个班级,在7班和8班中都有一个叫“小王”的同学,如果在学校的广播中呼叫“小王”时,7班和8班中的这2个人就纳闷了,你是喊谁呢!!!如果是“7班的小王”的话,那么就很明确了,那么此时的7班就是小王所在的范围,即命名空间

    globals、locals

    在之前学习变量的作用域时,经常会提到局部变量和全局变量,之所有称之为局部、全局,就是因为他们的自作用的区域不同,这就是作用域

LEGB 规则

Python 使用 LEGB 的顺序来查找一个符号对应的对象

locals -> enclosing function -> globals -> builtins
  • locals,当前所在命名空间(如函数、模块),函数的参数也属于命名空间内的变量
  • enclosing,外部嵌套函数的命名空间(闭包中常见)
def fun1():
  a = 10
  def fun2():
      # a 位于外部嵌套函数的命名空间
      print(a)
  • globals,全局变量,函数定义所在模块的命名空间
a = 1
def fun():
  # 需要通过 global 指令来声明全局变量
  global a
  # 修改全局变量,而不是创建一个新的 local 变量
  a = 2
  • builtins,内建模块的命名空间。
Python 在启动的时候会自动为我们载入很多内建的函数、类,
  比如 dict,list,type,print,这些都位于 __builtin__ 模块中,
  可以使用 dir(__builtin__) 来查看。
  这也是为什么我们在没有 import任何模块的情况下,
  就能使用这么多丰富的函数和功能了。

  在Python中,有一个内建模块,该模块中有一些常用函数;在Python启动后,
  且没有执行程序员所写的任何代码前,Python会首先加载该内建函数到内存。
  另外,该内建模块中的功能可以直接使用,不用在其前添加内建模块前缀,
  其原因是对函数、变量、类等标识符的查找是按LEGB法则,其中B即代表内建模块
  比如:内建模块中有一个abs()函数,其功能求绝对值,如abs(-20)将返回20。

==、is

  • is 是比较两个引用是否指向了同一个对象(引用比较)。
  • == 是比较两个对象是否相等。

深拷贝、浅拷贝

1. 浅拷贝

浅拷贝是对于一个对象的顶层拷贝
通俗的理解是:拷贝了引用,并没有拷贝内容

深拷贝
深拷贝是对于一个对象所有层次的拷贝(递归)

拷贝的其他方式
浅拷贝对不可变类型和可变类型的copy不同

私有化

  • xx: 公有变量
  • _x: 单前置下划线,私有化属性或方法,from somemodule import *禁止导入,类对象和子类可以访问
  • __xx:双前置下划线,避免与子类中的属性命名冲突,无法在外部直接访问(名字重整所以访问不到)
  • xx:双前后下划线,用户名字空间的魔法对象或属性。例如:init , __ 不要自己发明这样的名字
  • xx_:单后置下划线,用于避免与Python关键词的冲突

通过name mangling(名字重整(目的就是以防子类意外重写基类的方法或者属性)如:_Class__object)机制就可以访问private了。

#coding=utf-8

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

    def showperson(self):
        print(self.name)
        print(self._age)
        print(self.__taste)

    def dowork(self):
        self._work()
        self.__away()


    def _work(self):
        print('my _work')

    def __away(self):
        print('my __away')

        class Student(Person):
    def construction(self, name, age, taste):
        self.name = name
        self._age = age 
        self.__taste = taste

    def showstudent(self):
        print(self.name)
        print(self._age)
        print(self.__taste)

    @staticmethod
    def testbug():
        _Bug.showbug()

#模块内可以访问,当from  cur_module import *时,不导入
class _Bug(object):
    @staticmethod
    def showbug():
        print("showbug")

s1 = Student('jack', 25, 'football')
s1.showperson()
print('*'*20)

#无法访问__taste,导致报错
#s1.showstudent() 
s1.construction('rose', 30, 'basketball')
s1.showperson()
print('*'*20)

s1.showstudent()
print('*'*20)

Student.testbug()

总结

  • 父类中属性名为__名字的,子类不继承,子类不能访问
  • 如果在子类中向__名字赋值,那么会在子类中定义的一个与父类相同名字的属性
  • _名的变量、函数、类在使用from xxx import *时都不会被导入

属性property

1. 私有属性添加getter和setter方法

class Money(object):
    def __init__(self):
        self.__money = 0

    def getMoney(self):
        return self.__money

    def setMoney(self, value):
        if isinstance(value, int):
            self.__money = value
        else:
            print("error:不是整型数字")

2. 使用property升级getter和setter方法

class Money(object):
    def __init__(self):
        self.__money = 0

    def getMoney(self):
        return self.__money

    def setMoney(self, value):
        if isinstance(value, int):
            self.__money = value
        else:
            print("error:不是整型数字")
    money = property(getMoney, setMoney)

3. 使用property取代getter和setter方法

@property成为属性函数,可以对属性赋值时做必要的检查,并保证代码的清晰短小,主要有2个作用

将方法转换为只读
重新实现一个属性的设置和读取方法,可做边界判定

class Money(object):
    def __init__(self):
        self.__money = 0

    @property
    def money(self):
        return self.__money

    @money.setter
    def money(self, value):
        if isinstance(value, int):
            self.__money = value
        else:
            print("error:不是整型数字")

文章作者: 邓滔
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 邓滔 !
评论
  目录