Skip to content Skip to main navigation Skip to footer

python

Python本地与全局命名空间的用法

Python本地与全局命名空间是如何来使用的呢?下面的内容将会通过具体的实例来演示Python本地与全局命名空间的使用方法及相关技巧:

本文实例讲述了Python本地与全局命名空间用法。分享给大家供大家参考。具体如下:

x = 1
def fun(a):
  b=3
  x=4
  def sub(c):
    d=b
    global x
    x = 7
    print ("Nested Functionn=================")
    print locals()
  sub(5)
  print ("nFunctionn=================")
  print locals()
  print locals()["x"]
  print globals()["x"]
print ("nGlobalsn=================")
print globals()
fun(2)
///scope.py
Globals
=================
{'x': 1,
 '__file__':
'C:\books\python\CH1\code\scope.py',
 'fun': <function fun at 0x008D7570>,
 't': <class '__main__.t'>,
 'time': <module 'time' (built-in)>,. . .}
Nested Function
=================
{'c': 5, 'b': 3, 'd': 3}
Function
=================
{'a': 2, 'x': 4, 'b': 3, 'sub':
  <function sub at 0x008D75F0>}
4
7
 


Python本地与全局命名空间就是这样,欢迎大家参考。。。。

Python读取键盘输入的2种方法

Python读取键盘输入是如何来实现的呢?下面的内容将会通过具体的实例来演示Python读取键盘输入的实现方法及相关技巧:

Python提供了两个内置函数从标准输入读入一行文本,默认的标准输入是键盘。如下:

1.raw_input
2.input

raw_input函数

raw_input() 函数从标准输入读取一个行,并返回一个字符串(去掉结尾的换行符):

str = raw_input("Enter your input: ");
print "Received input is : ", str
 

这将提示你输入任意字符串,然后在屏幕上显示相同的字符串。当我输入”Hello Python!”,它的输出如下:

Enter your input: Hello Python
Received input is :  Hello Python
 

input函数

input() 函数和raw_input() 函数基本可以互换,但是input会假设你的输入是一个有效的Python表达式,并返回运算结果。这应该是两者的最大区别。

str = input("Enter your input: ");
print "Received input is : ", str
 

这会产生如下的对应着输入的结果:

Enter your input: [x*5 for x in range(2,10,2)]
Recieved input is :  [10, 20, 30, 40]
 


Python读取键盘输入就是这样,欢迎大家参考。。。。

wxPython使用系统剪切板的方法

wxPython系统剪切板是如何来使用的呢?下面的内容将会通过具体的实例来演示wxPython系统剪切板的使用方法及相关技巧:

本文实例讲述了wxPython使用系统剪切板的方法。分享给大家供大家参考。具体如下:

程序运行效果如下图所示:

wxPython使用系统剪切板的方法
wxPython使用系统剪切板的方法

主要代码如下:

import wx
########################################################################
class ClipboardPanel(wx.Panel):
  """"""
  #----------------------------------------------------------------------
  def __init__(self, parent):
    """Constructor"""
    wx.Panel.__init__(self, parent)
    lbl = wx.StaticText(self, label="Enter text to copy to clipboard:")
    self.text = wx.TextCtrl(self, style=wx.TE_MULTILINE)
    copyBtn = wx.Button(self, label="Copy")
    copyBtn.Bind(wx.EVT_BUTTON, self.onCopy)
    copyFlushBtn = wx.Button(self, label="Copy and Flush")
    copyFlushBtn.Bind(wx.EVT_BUTTON, self.onCopyAndFlush)
    sizer = wx.BoxSizer(wx.VERTICAL)
    sizer.Add(lbl, 0, wx.ALL, 5)
    sizer.Add(self.text, 1, wx.EXPAND)
    sizer.Add(copyBtn, 0, wx.ALL|wx.CENTER, 5)
    sizer.Add(copyFlushBtn, 0, wx.ALL|wx.CENTER, 5)
    self.SetSizer(sizer)
  #----------------------------------------------------------------------
  def onCopy(self, event):
    """"""
    self.dataObj = wx.TextDataObject()
    self.dataObj.SetText(self.text.GetValue())
    if wx.TheClipboard.Open():
      wx.TheClipboard.SetData(self.dataObj)
      wx.TheClipboard.Close()
    else:
      wx.MessageBox("Unable to open the clipboard", "Error")
  #----------------------------------------------------------------------
  def onCopyAndFlush(self, event):
    """"""
    self.dataObj = wx.TextDataObject()
    self.dataObj.SetText(self.text.GetValue())
    if wx.TheClipboard.Open():
      wx.TheClipboard.SetData(self.dataObj)
      wx.TheClipboard.Flush()
    else:
      wx.MessageBox("Unable to open the clipboard", "Error")
    self.GetParent().Close()
########################################################################
class ClipboardFrame(wx.Frame):
  """"""
  #----------------------------------------------------------------------
  def __init__(self):
    """Constructor"""
    wx.Frame.__init__(self, None, title="Clipboard Tutorial")
    panel = ClipboardPanel(self)
    self.Show()
if __name__ == "__main__":
  app = wx.App(False)
  frame = ClipboardFrame()
  app.MainLoop()
 


wxPython系统剪切板就是这样,欢迎大家参考。。。。

python实用代码片段

下面的内容主要介绍了python实用代码片段,欢迎大家参考:

获取一个类的所有子类

def itersubclasses(cls, _seen=None):
    """Generator over all subclasses of a given class in depth first order."""
    if not isinstance(cls, type):
        raise TypeError(_('itersubclasses must be called with '
                          'new-style classes, not %.100r') % cls)
    _seen = _seen or set()
    try:
        subs = cls.__subclasses__()
    except TypeError:   # fails only when cls is type
        subs = cls.__subclasses__(cls)
    for sub in subs:
        if sub not in _seen:
            _seen.add(sub)
            yield sub
            for sub in itersubclasses(sub, _seen):
                yield sub
 

简单的线程配合

import threading
is_done = threading.Event()
consumer = threading.Thread(
    target=self.consume_results,
    args=(key, self.task, runner.result_queue, is_done))
consumer.start()
self.duration = runner.run(
        name, kw.get("context", {}), kw.get("args", {}))
is_done.set()
consumer.join() #主线程堵塞,直到consumer运行结束
 

多说一点,threading.Event()也可以被替换为threading.Condition(),condition有notify(), wait(), notifyAll()。解释如下:

The wait() method releases the lock, and then blocks until it is awakened by a notify() or notifyAll() call for the same condition variable in another thread. Once awakened, it re-acquires the lock and returns. It is also possible to specify a timeout.
The notify() method wakes up one of the threads waiting for the condition variable, if any are waiting. The notifyAll() method wakes up all threads waiting for the condition variable.
Note: the notify() and notifyAll() methods don't release the lock; this means that the thread or threads awakened will not return from their wait() call immediately, but only when the thread that called notify() or notifyAll() finally relinquishes ownership of the lock.
 

# Consume one item
cv.acquire()
while not an_item_is_available():
    cv.wait()
get_an_available_item()
cv.release()
# Produce one item
cv.acquire()
make_an_item_available()
cv.notify()
cv.release()
 

计算运行时间

class Timer(object):
    def __enter__(self):
        self.error = None
        self.start = time.time()
        return self
    def __exit__(self, type, value, tb):
        self.finish = time.time()
        if type:
            self.error = (type, value, tb)
    def duration(self):
        return self.finish - self.start
with Timer() as timer:
    func()
return timer.duration()
 

元类

__new__()方法接收到的参数依次是:
当前准备创建的类的对象;
类的名字;
类继承的父类集合;
类的方法集合;

class ModelMetaclass(type):
    def __new__(cls, name, bases, attrs):
        if name=='Model':
            return type.__new__(cls, name, bases, attrs)
        mappings = dict()
        for k, v in attrs.iteritems():
            if isinstance(v, Field):
                print('Found mapping: %s==>%s' % (k, v))
                mappings[k] = v
        for k in mappings.iterkeys():
            attrs.pop(k)
        attrs['__table__'] = name # 假设表名和类名一致
        attrs['__mappings__'] = mappings # 保存属性和列的映射关系
        return type.__new__(cls, name, bases, attrs)
class Model(dict):
    __metaclass__ = ModelMetaclass
    def __init__(self, **kw):
        super(Model, self).__init__(**kw)
    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError:
            raise AttributeError(r"'Model' object has no attribute '%s'" % key)
    def __setattr__(self, key, value):
        self[key] = value
    def save(self):
        fields = []
        params = []
        args = []
        for k, v in self.__mappings__.iteritems():
            fields.append(v.name)
            params.append('&#63;')
            args.append(getattr(self, k, None))
        sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
        print('SQL: %s' % sql)
        print('ARGS: %s' % str(args))
class Field(object):
    def __init__(self, name, column_type):
        self.name = name
        self.column_type = column_type
    def __str__(self):
        return '<%s:%s>' % (self.__class__.__name__, self.name)
class StringField(Field):
    def __init__(self, name):
        super(StringField, self).__init__(name, 'varchar(100)')
class IntegerField(Field):
    def __init__(self, name):
        super(IntegerField, self).__init__(name, 'bigint')
class User(Model):
    # 定义类的属性到列的映射:
    id = IntegerField('id')
    name = StringField('username')
    email = StringField('email')
    password = StringField('password')
# 创建一个实例:
u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
# 保存到数据库:
u.save()
 

输出如下:

Found model: User
Found mapping: email ==> <stringField:email>
Found mapping: password ==> <stringField:password>
Found mapping: id ==> <integerField:uid>
Found mapping: name ==> <stringField:username>
SQL: insert into User (password,email,username,uid) values (&#63;,&#63;,&#63;,&#63;)
ARGS: ['my-pwd', 'test@orm.org', 'Michael', 12345]
 

SQLAlchemy简单使用

# 导入:
from sqlalchemy import Column, String, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
# 创建对象的基类:
Base = declarative_base()
# 定义User对象:
class User(Base):
    # 表的名字:
    __tablename__ = 'user'
    # 表的结构:
    id = Column(String(20), primary_key=True)
    name = Column(String(20))
# 初始化数据库连接:
engine = create_engine('mysql+mysqlconnector://root:password@localhost:3306/test') # '数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名'
# 创建DBSession类型:
DBSession = sessionmaker(bind=engine)
# 创建新User对象:
new_user = User(id='5', name='Bob')
# 添加到session:
session.add(new_user)
# 提交即保存到数据库:
session.commit()
# 创建Query查询,filter是where条件,最后调用one()返回唯一行,如果调用all()则返回所有行:
user = session.query(User).filter(User.id=='5').one()
# 关闭session:
session.close()
 

WSGI简单使用和Web框架Flask的简单使用

from wsgiref.simple_server import make_server
def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return '<h1>Hello, web!</h1>'
# 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
httpd = make_server('', 8000, application)
print "Serving HTTP on port 8000..."
# 开始监听HTTP请求:
httpd.serve_forever()
 

了解了WSGI框架,我们发现:其实一个Web App,就是写一个WSGI的处理函数,针对每个HTTP请求进行响应。
但是如何处理HTTP请求不是问题,问题是如何处理100个不同的URL。
一个最简单和最土的想法是从environ变量里取出HTTP请求的信息,然后逐个判断。

from flask import Flask
from flask import request
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def home():
    return '<h1>Home</h1>'
@app.route('/signin', methods=['GET'])
def signin_form():
    return '''<form action="/signin" method="post">
              <p><input name="username"></p>
              <p><input name="password" type="password"></p>
              <p><button type="submit">Sign In</button></p>
              </form>'''
@app.route('/signin', methods=['POST'])
def signin():
    # 需要从request对象读取表单内容:
    if request.form['username']=='admin' and request.form['password']=='password':
        return '<h3>Hello, admin!</h3>'
    return '<h3>Bad username or password.</h3>'
if __name__ == '__main__':
    app.run()
 

格式化显示json

print(json.dumps(data, indent=4))
# 或者
import pprint
pprint.pprint(data)
 

实现类似Java或C中的枚举

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import itertools
import sys
class ImmutableMixin(object):
    _inited = False
    def __init__(self):
        self._inited = True
    def __setattr__(self, key, value):
        if self._inited:
            raise Exception("unsupported action")
        super(ImmutableMixin, self).__setattr__(key, value)
class EnumMixin(object):
    def __iter__(self):
        for k, v in itertools.imap(lambda x: (x, getattr(self, x)), dir(self)):
            if not k.startswith('_'):
                yield v
class _RunnerType(ImmutableMixin, EnumMixin):
    SERIAL = "serial"
    CONSTANT = "constant"
    CONSTANT_FOR_DURATION = "constant_for_duration"
    RPS = "rps"
if __name__=="__main__":
    print _RunnerType.CONSTANT
 

创建文件时指定权限

import os
def write_to_file(path, contents, umask=None):
    """Write the given contents to a file
    :param path: Destination file
    :param contents: Desired contents of the file
    :param umask: Umask to set when creating this file (will be reset)
    """
    if umask:
        saved_umask = os.umask(umask)
    try:
        with open(path, 'w') as f:
            f.write(contents)
    finally:
        if umask:
            os.umask(saved_umask)
if __name__ == '__main__':
    write_to_file('/home/kong/tmp', 'test', 31)
    # Then you will see a file is created with permission 640.
    # Warning: If the file already exists, its permission will not be changed.
    # Note:For file, default all permission is 666, and 777 for directory.
 

多进程并发执行

import multiprocessing
import time
import os
def run(flag):
    print "flag: %s, sleep 2s in run" % flag
    time.sleep(2)
    print "%s exist" % flag
    return flag
if __name__ == '__main__':
    pool = multiprocessing.Pool(3)
    iter_result = pool.imap(run, xrange(6))
    print "sleep 5snn"
    time.sleep(5)
    for i in range(6):
        try:
            result = iter_result.next(600)
        except multiprocessing.TimeoutError as e:
            raise
        print result
    pool.close()
    pool.join()
 

运行时自动填充函数参数

import decorator
def default_from_global(arg_name, env_name):
    def default_from_global(f, *args, **kwargs):
        id_arg_index = f.func_code.co_varnames.index(arg_name)
        args = list(args)
        if args[id_arg_index] is None:
            args[id_arg_index] = get_global(env_name)
            if not args[id_arg_index]:
                print("Missing argument: --%(arg_name)s" % {"arg_name": arg_name})
                return(1)
        return f(*args, **kwargs)
    return decorator.decorator(default_from_global)
# 如下是一个装饰器,可以用在需要自动填充参数的函数上。功能是:
# 如果没有传递函数的deploy_id参数,那么就从环境变量中获取(调用自定义的get_global函数)
with_default_deploy_id = default_from_global('deploy_id', ENV_DEPLOYMENT)
 

嵌套装饰器

validator函数装饰func1,func1使用时接收参数(*arg, **kwargs),而func1又装饰func2(其实就是Rally中的scenario函数),给func2增加validators属性,是一个函数的列表,函数的接收参数config, clients, task。这些函数最终调用func1,传入参数(config, clients, task, *args, **kwargs),所以func1定义时参数是(config, clients, task, *arg, **kwargs)
最终实现的效果是,func2有很多装饰器,每个都会接收自己的参数,做一些校验工作。

def validator(fn):
    """Decorator that constructs a scenario validator from given function.
    Decorated function should return ValidationResult on error.
    :param fn: function that performs validation
    :returns: rally scenario validator
    """
    def wrap_given(*args, **kwargs):
        """Dynamic validation decorator for scenario.
        :param args: the arguments of the decorator of the benchmark scenario
        ex. @my_decorator("arg1"), then args = ('arg1',)
        :param kwargs: the keyword arguments of the decorator of the scenario
        ex. @my_decorator(kwarg1="kwarg1"), then kwargs = {"kwarg1": "kwarg1"}
        """
        def wrap_validator(config, clients, task):
            return (fn(config, clients, task, *args, **kwargs) or
                    ValidationResult())
        def wrap_scenario(scenario):
            wrap_validator.permission = getattr(fn, "permission",
                                                consts.EndpointPermission.USER)
            if not hasattr(scenario, "validators"):
                scenario.validators = []
            scenario.validators.append(wrap_validator)
            return scenario
        return wrap_scenario
    return wrap_given
 

inspect库的一些常见用法

inspect.getargspec(func) 获取函数参数的名称和默认值,返回一个四元组(args, varargs, keywords, defaults),其中:
args是参数名称的列表;
varargs和keywords是*号和**号的变量名称;
defaults是参数默认值的列表;

inspect.getcallargs(func[, *args][, **kwds]) 绑定函数参数。返回绑定后函数的入参字典。

python中的私有属性和函数

Python把以两个或以上下划线字符开头且没有以两个或以上下划线结尾的变量当作私有变量。私有变量会在代码生成之前被转换为长格式(变为公有),这个过程叫”Private name mangling”,如类A里的__private标识符将被转换为_A__private,但当类名全部以下划线命名的时候,Python就不再执行轧压。而且,虽然叫私有变量,仍然有可能被访问或修改(使用_classname__membername),所以, 总结如下:

无论是单下划线还是双下划线开头的成员,都是希望外部程序开发者不要直接使用这些成员变量和这些成员函数,只是双下划线从语法上能够更直接的避免错误的使用,但是如果按照_类名__成员名则依然可以访问到。单下划线的在动态调试时可能会方便一些,只要项目组的人都遵守下划线开头的成员不直接使用,那使用单下划线或许会更好。


python实用代码片段就是这样,欢迎大家参考。。。。

Python中的描述符介绍

Python中的描述符是如何来使用的呢?下面的内容将会通过具体的实例来演示Python中的描述符的使用方法及相关技巧:

Python中包含了许多内建的语言特性,它们使得代码简洁且易于理解。这些特性包括列表/集合/字典推导式,属性(property)、以及装饰器(decorator)。对于大部分特性来说,这些“中级”的语言特性有着完善的文档,并且易于学习。

但是这里有个例外,那就是描述符。至少对于我来说,描述符是Python语言核心中困扰我时间最长的一个特性。这里有几点原因如下:

1.有关描述符的官方文档相当难懂,而且没有包含优秀的示例告诉你为什么需要编写描述符(我得为Raymond Hettinger辩护一下,他写的其他主题的Python文章和视频对我的帮助还是非常大的)
2.编写描述符的语法显得有些怪异
3.自定义描述符可能是Python中用的最少的特性,因此你很难在开源项目中找到优秀的示例

但是一旦你理解了之后,描述符的确还是有它的应用价值的。这篇文章告诉你描述符可以用来做什么,以及为什么应该引起你的注意。

一句话概括:描述符就是可重用的属性

在这里我要告诉你:从根本上讲,描述符就是可以重复使用的属性。也就是说,描述符可以让你编写这样的代码:

f = Foo()
b = f.bar
f.bar = c
del f.bar
 

而在解释器执行上述代码时,当发现你试图访问属性(b = f.bar)、对属性赋值(f.bar = c)或者删除一个实例变量的属性(del f.bar)时,就会去调用自定义的方法。

让我们先来解释一下为什么把对函数的调用伪装成对属性的访问是大有好处的。

property——把函数调用伪装成对属性的访问

想象一下你正在编写管理电影信息的代码。你最后写好的Movie类可能看上去是这样的:

class Movie(object):
    def __init__(self, title, rating, runtime, budget, gross):
        self.title = title
        self.rating = rating
        self.runtime = runtime
        self.budget = budget
        self.gross = gross
    def profit(self):
        return self.gross - self.budget
 

你开始在项目的其他地方使用这个类,但是之后你意识到:如果不小心给电影打了负分怎么办?你觉得这是错误的行为,希望Movie类可以阻止这个错误。 你首先想到的办法是将Movie类修改为这样:

class Movie(object):
    def __init__(self, title, rating, runtime, budget, gross):
        self.title = title
        self.rating = rating
        self.runtime = runtime
        self.gross = gross
        if budget < 0:
            raise ValueError("Negative value not allowed: %s" % budget)
        self.budget = budget
    def profit(self):
        return self.gross - self.budget
 &#91;/code&#93;</p>
<p>但这行不通。因为其他部分的代码都是直接通过Movie.budget来赋值的——这个新修改的类只会在init方法中捕获错误的数据,但对于已经存在的类实例就无能为力了。如果有人试着运行m.budget = -100,那么谁也没法阻止。作为一个Python程序员同时也是电影迷,你该怎么办?</p>
<p>幸运的是,Python的property解决了这个问题。如果你从未见过property的用法,下面是一个示例:

class Movie(object):
    def __init__(self, title, rating, runtime, budget, gross):
        self._budget = None
        self.title = title
        self.rating = rating
        self.runtime = runtime
        self.gross = gross
        self.budget = budget
    @property
    def budget(self):
        return self._budget
    @budget.setter
    def budget(self, value):
        if value < 0:
            raise ValueError("Negative value not allowed: %s" % value)
        self._budget = value
    def profit(self):
        return self.gross - self.budget
m = Movie('Casablanca', 97, 102, 964000, 1300000)
print m.budget       # calls m.budget(), returns result
try:
    m.budget = -100  # calls budget.setter(-100), and raises ValueError
except ValueError:
    print "Woops. Not allowed"
964000
Woops. Not allowed
 &#91;/code&#93;</p>
<p>我们用@property装饰器指定了一个getter方法,用@budget.setter装饰器指定了一个setter方法。当我们这么做时,每当有人试着访问budget属性,Python就会自动调用相应的getter/setter方法。比方说,当遇到m.budget = value这样的代码时就会自动调用budget.setter。</p>
<p>花点时间来欣赏一下Python这么做是多么的优雅:如果没有property,我们将不得不把所有的实例属性隐藏起来,提供大量显式的类似get_budget和set_budget方法。像这样编写类的话,使用起来就会不断的去调用这些getter/setter方法,这看起来就像臃肿的Java代码一样。更糟的是,如果我们不采用这种编码风格,直接对实例属性进行访问。那么稍后就没法以清晰的方式增加对非负数的条件检查——我们不得不重新创建set_budget方法,然后搜索整个工程中的源代码,将m.budget = value这样的代码替换为m.set_budget(value)。太蛋疼了!!</p>
<p>因此,property让我们将自定义的代码同变量的访问/设定联系在了一起,同时为你的类保持一个简单的访问属性的接口。干得漂亮!</p>
<p><strong>property的不足</strong></p>
<p>对property来说,最大的缺点就是它们不能重复使用。举个例子,假设你想为rating,runtime和gross这些字段也添加非负检查。下面是修改过的新类:

class Movie(object):
    def __init__(self, title, rating, runtime, budget, gross):
        self._rating = None
        self._runtime = None
        self._budget = None
        self._gross = None
        self.title = title
        self.rating = rating
        self.runtime = runtime
        self.gross = gross
        self.budget = budget
    #nice
    @property
    def budget(self):
        return self._budget
    @budget.setter
    def budget(self, value):
        if value < 0:
            raise ValueError("Negative value not allowed: %s" % value)
        self._budget = value
    #ok
    @property
    def rating(self):
        return self._rating
    @rating.setter
    def rating(self, value):
        if value < 0:
            raise ValueError("Negative value not allowed: %s" % value)
        self._rating = value
    #uhh...
    @property
    def runtime(self):
        return self._runtime
    @runtime.setter
    def runtime(self, value):
        if value < 0:
            raise ValueError("Negative value not allowed: %s" % value)
        self._runtime = value
    #is this forever&#63;
    @property
    def gross(self):
        return self._gross
    @gross.setter
    def gross(self, value):
        if value < 0:
            raise ValueError("Negative value not allowed: %s" % value)
        self._gross = value
    def profit(self):
        return self.gross - self.budget
 &#91;/code&#93;</p>
<p>可以看到代码增加了不少,但重复的逻辑也出现了不少。虽然property可以让类从外部看起来接口整洁漂亮,但是却做不到内部同样整洁漂亮。</p>
<p><strong>描述符登场(最终的大杀器)</strong></p>
<p>这就是描述符所解决的问题。描述符是property的升级版,允许你为重复的property逻辑编写单独的类来处理。下面的示例展示了描述符是如何工作的(现在还不必担心NonNegative类的实现):

from weakref import WeakKeyDictionary
class NonNegative(object):
    """A descriptor that forbids negative values"""
    def __init__(self, default):
        self.default = default
        self.data = WeakKeyDictionary()
    def __get__(self, instance, owner):
        # we get here when someone calls x.d, and d is a NonNegative instance
        # instance = x
        # owner = type(x)
        return self.data.get(instance, self.default)
    def __set__(self, instance, value):
        # we get here when someone calls x.d = val, and d is a NonNegative instance
        # instance = x
        # value = val
        if value < 0:
            raise ValueError("Negative value not allowed: %s" % value)
        self.data&#91;instance&#93; = value
class Movie(object):
    #always put descriptors at the class-level
    rating = NonNegative(0)
    runtime = NonNegative(0)
    budget = NonNegative(0)
    gross = NonNegative(0)
    def __init__(self, title, rating, runtime, budget, gross):
        self.title = title
        self.rating = rating
        self.runtime = runtime
        self.budget = budget
        self.gross = gross
    def profit(self):
        return self.gross - self.budget
m = Movie('Casablanca', 97, 102, 964000, 1300000)
print m.budget  # calls Movie.budget.__get__(m, Movie)
m.rating = 100  # calls Movie.budget.__set__(m, 100)
try:
    m.rating = -1   # calls Movie.budget.__set__(m, -100)
except ValueError:
    print "Woops, negative value"
964000
Woops, negative value
 &#91;/code&#93;</p>
<p>这里引入了一些新的语法,我们一条条的来看:
NonNegative是一个描述符对象,因为它定义了__get__,__set__或__delete__方法。
Movie类现在看起来非常清晰。我们在类的层面上创建了4个描述符,把它们当做普通的实例属性。显然,描述符在这里为我们做非负检查。</p>
<p><strong>访问描述符</strong></p>
<p>当解释器遇到print m.buget时,它就会把budget当作一个带有__get__ 方法的描述符,调用Movie.budget.__get__方法并将方法的返回值打印出来,而不是直接传递m.budget来打印。这和你访问一个property相似,Python自动调用一个方法,同时返回结果。</p>
<p>__get__接收2个参数:一个是点号左边的实例对象(在这里,就是m.budget中的m),另一个是这个实例的类型(Movie)。在一些Python文档中,Movie被称作描述符的所有者(owner)。如果我们需要访问Movie.budget,Python将会调用Movie.budget.__get__(None, Movie)。可以看到,第一个参数要么是所有者的实例,要么是None。这些输入参数可能看起来很怪,但是这里它们告诉了你描述符属于哪个对象的一部分。当我们看到NonNegative类的实现时这一切就合情合理了。</p>
<p><strong>对描述符赋值</strong></p>
<p>当解释器看到m.rating = 100时,Python识别出rating是一个带有set方法的描述符,于是就调用Movie.rating.__set__(m, 100)。和__get__一样,__set__的第一个参数是点号左边的类实例(m.rating = 100中的m)。第二个参数是所赋的值(100)。</p>
<p><strong>删除描述符</strong></p>
<p>为了说明的完整,这里提一下删除。如果你调用del m.budget,Python就会调用Movie.budget.__delete__(m)。</p>
<p><strong>NonNegative类是如何工作的?</strong></p>
<p>带着前面的困惑,我们终于要揭示NonNegative类是如何工作的了。每个NonNegative的实例都维护着一个字典,其中保存着所有者实例和对应数据的映射关系。当我们调用m.budget时,__get__方法会查找与m相关联的数据,并返回这个结果(如果这个值不存在,则会返回一个默认值)。__set__采用的方式相同,但是这里会包含额外的非负检查。我们使用WeakKeyDictionary来取代普通的字典以防止内存泄露——我们可不想仅仅因为它在描述符的字典中就让一个无用&#8232;的实例一直存活着。</p>
<p>使用描述符会有一点别扭。因为它们作用于类的层次上,每一个类实例都共享同一个描述符。这就意味着对不同的实例对象而言,描述符不得不手动地管理不同的状态,同时需要显式的将类实例作为第一个参数准确传递给__get__、__set__以及__delete__方法。</p>
<p>我希望这个例子解释清楚了描述符可以用来做什么——它们提供了一种方法将property的逻辑隔离到单独的类中来处理。如果你发现自己正在不同的property之间重复着相同的逻辑,那么本文也许会成为一个线索供你思考为何用描述符重构代码是值得一试的。</p>
<p><strong>秘诀和陷阱</strong></p>
<p><strong>把描述符放在类的层次上(class level)</strong></p>
<p>为了让描述符能够正常工作,它们必须定义在类的层次上。如果你不这么做,那么Python无法自动为你调用__get__和__set__方法。

class Broken(object):
    y = NonNegative(5)
    def __init__(self):
        self.x = NonNegative(0)  # NOT a good descriptor
b = Broken()
print "X is %s, Y is %s" % (b.x, b.y)
X is <__main__.NonNegative object at 0x10432c250>, Y is 5
 

可以看到,访问类层次上的描述符y可以自动调用__get__。但是访问实例层次上的描述符x只会返回描述符本身,真是魔法一般的存在啊。

确保实例的数据只属于实例本身

你可能会像这样编写NonNegative描述符:

class BrokenNonNegative(object):
    def __init__(self, default):
        self.value = default
    def __get__(self, instance, owner):
        return self.value
    def __set__(self, instance, value):
        if value < 0:
            raise ValueError("Negative value not allowed: %s" % value)
        self.value = value
class Foo(object):
    bar = BrokenNonNegative(5)
f = Foo()
try:
    f.bar = -1
except ValueError:
    print "Caught the invalid assignment"
Caught the invalid assignment
 &#91;/code&#93;</p>
<p>这么做看起来似乎能正常工作。但这里的问题就在于所有Foo的实例都共享相同的bar,这会产生一些令人痛苦的结果:

class Foo(object):
    bar = BrokenNonNegative(5)
f = Foo()
g = Foo()
print "f.bar is %sng.bar is %s" % (f.bar, g.bar)
print "Setting f.bar to 10"
f.bar = 10
print "f.bar is %sng.bar is %s" % (f.bar, g.bar)  #ouch
f.bar is 5
g.bar is 5
Setting f.bar to 10
f.bar is 10
g.bar is 10
 

这就是为什么我们要在NonNegative中使用数据字典的原因。__get__和__set__的第一个参数告诉我们需要关心哪一个实例。NonNegative使用这个参数作为字典的key,为每一个Foo实例单独保存一份数据。

class Foo(object):
    bar = NonNegative(5)
f = Foo()
g = Foo()
print "f.bar is %sng.bar is %s" % (f.bar, g.bar)
print "Setting f.bar to 10"
f.bar = 10
print "f.bar is %sng.bar is %s" % (f.bar, g.bar)  #better
f.bar is 5
g.bar is 5
Setting f.bar to 10
f.bar is 10
g.bar is 5
 

这就是描述符最令人感到别扭的地方(坦白的说,我不理解为什么Python不让你在实例的层次上定义描述符,并且总是需要将实际的处理分发给get和set。这么做行不通一定是有原因的)

注意不可哈希的描述符所有者

NonNegative类使用了一个字典来单独保存专属于实例的数据。这个一般来说是没问题的,除非你用到了不可哈希(unhashable)的对象:

class MoProblems(list):  #you can't use lists as dictionary keys
    x = NonNegative(5)
m = MoProblems()
print m.x  # womp womp
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-dd73b177bd8d> in <module>()
      3
      4 m = MoProblems()
----> 5 print m.x  # womp womp
<ipython-input-3-6671804ce5d5> in __get__(self, instance, owner)
      9         # instance = x
     10         # owner = type(x)
---> 11         return self.data.get(instance, self.default)
     12
     13     def __set__(self, instance, value):
TypeError: unhashable type: 'MoProblems'
 

因为MoProblems的实例(list的子类)是不可哈希的,因此它们不能为MoProblems.x用做数据字典的key。有一些方法可以规避这个问题,但是都不完美。最好的方法可能就是给你的描述符加标签了。

class Descriptor(object):
    def __init__(self, label):
        self.label = label
    def __get__(self, instance, owner):
        print '__get__', instance, owner
        return instance.__dict__.get(self.label)
    def __set__(self, instance, value):
        print '__set__'
        instance.__dict__[self.label] = value
class Foo(list):
    x = Descriptor('x')
    y = Descriptor('y')
f = Foo()
f.x = 5
print f.x
__set__
__get__ [] <class '__main__.Foo'>
5
 

这种方法依赖于Python的方法解析顺序(即,MRO)。我们给Foo中的每个描述符加上一个标签名,名称和我们赋值给描述符的变量名相同,比如x = Descriptor(‘x')。之后,描述符将特定于实例的数据保存在f.__dict__['x']中。这个字典条目通常是当我们请求f.x时Python给出的返回值。然而,由于Foo.x 是一个描述符,Python不能正常的使用f.__dict__[‘x'],但是描述符可以安全的在这里存储数据。只是要记住,不要在别的地方也给这个描述符添加标签。

class Foo(object):
    x = Descriptor('y')
f = Foo()
f.x = 5
print f.x
f.y = 4    #oh no!
print f.x
__set__
__get__ <__main__.Foo object at 0x10432c810> <class '__main__.Foo'>
5
__get__ <__main__.Foo object at 0x10432c810> <class '__main__.Foo'>
4
 

我不喜欢这种方式,因为这样的代码很脆弱也有很多微妙之处。但这个方法的确很普遍,可以用在不可哈希的所有者类上。David Beazley在他的书中用到了这个方法。

在元类中使用带标签的描述符

由于描述符的标签名和赋给它的变量名相同,所以有人使用元类来自动处理这个簿记(bookkeeping)任务。

class Descriptor(object):
    def __init__(self):
        #notice we aren't setting the label here
        self.label = None
    def __get__(self, instance, owner):
        print '__get__. Label = %s' % self.label
        return instance.__dict__.get(self.label, None)
    def __set__(self, instance, value):
        print '__set__'
        instance.__dict__[self.label] = value
class DescriptorOwner(type):
    def __new__(cls, name, bases, attrs):
        # find all descriptors, auto-set their labels
        for n, v in attrs.items():
            if isinstance(v, Descriptor):
                v.label = n
        return super(DescriptorOwner, cls).__new__(cls, name, bases, attrs)
class Foo(object):
    __metaclass__ = DescriptorOwner
    x = Descriptor()
f = Foo()
f.x = 10
print f.x
__set__
__get__. Label = x
10
 

我不会去解释有关元类的细节——参考文献中David Beazley已经在他的文章中解释的很清楚了。 需要指出的是元类自动的为描述符添加标签,并且和赋给描述符的变量名字相匹配。

尽管这样解决了描述符的标签和变量名不一致的问题,但是却引入了复杂的元类。虽然我很怀疑,但是你可以自行判断这么做是否值得。

访问描述符的方法

描述符仅仅是类,也许你想要为它们增加一些方法。举个例子,描述符是一个用来回调property的很好的手段。比如我们想要一个类的某个部分的状态发生变化时就立刻通知我们。下面的大部分代码是用来做这个的:

class CallbackProperty(object):
"""A property that will alert observers when upon updates"""
def __init__(self, default=None):
self.data = WeakKeyDictionary()
self.default = default
self.callbacks = WeakKeyDictionary()
def __get__(self, instance, owner):
return self.data.get(instance, self.default)
def __set__(self, instance, value):
for callback in self.callbacks.get(instance, []):
# alert callback function of new value
callback(value)
self.data[instance] = value
def add_callback(self, instance, callback):
"""Add a new function to call everytime the descriptor updates"""
#but how do we get here?!?!
if instance not in self.callbacks:
self.callbacks[instance] = [] self.callbacks[instance].append(callback)
class BankAccount(object):
balance = CallbackProperty(0)
def low_balance_warning(value):
if value < 100: print "You are poor" ba = BankAccount() # will not work -- try it #ba.balance.add_callback(ba, low_balance_warning) [/code]

这是一个很有吸引力的模式——我们可以自定义回调函数用来响应一个类中的状态变化,而且完全无需修改这个类的代码。这样做可真是替人分忧解难呀。现在,我们所要做的就是调用ba.balance.add_callback(ba, low_balance_warning),以使得每次balance变化时low_balance_warning都会被调用。

但是我们是如何做到的呢?当我们试图访问它们时,描述符总是会调用__get__。就好像add_callback方法是无法触及的一样!其实关键在于利用了一种特殊的情况,即,当从类的层次访问时,__get__方法的第一个参数是None。

class CallbackProperty(object):
"""A property that will alert observers when upon updates"""
def __init__(self, default=None):
self.data = WeakKeyDictionary()
self.default = default
self.callbacks = WeakKeyDictionary()
def __get__(self, instance, owner):
if instance is None:
return self
return self.data.get(instance, self.default)
def __set__(self, instance, value):
for callback in self.callbacks.get(instance, []):
# alert callback function of new value
callback(value)
self.data[instance] = value
def add_callback(self, instance, callback):
"""Add a new function to call everytime the descriptor within instance updates"""
if instance not in self.callbacks:
self.callbacks[instance] = [] self.callbacks[instance].append(callback)
class BankAccount(object):
balance = CallbackProperty(0)
def low_balance_warning(value):
if value < 100: print "You are now poor" ba = BankAccount() BankAccount.balance.add_callback(ba, low_balance_warning) ba.balance = 5000 print "Balance is %s" % ba.balance ba.balance = 99 print "Balance is %s" % ba.balance Balance is 5000 You are now poor Balance is 99 [/code]

结语

希望你现在对描述符是什么和它们的适用场景有了一个认识。前进吧骚年!


Python中的描述符就是这样,欢迎大家参考。。。。

Python建立SSH连接的方法介绍

Python建立SSH连接是如何来实现的呢?下面的内容将会通过具体的实例来演示Python建立SSH连接的实现方法及相关技巧:

本文实例讲述了Python实现建立SSH连接的方法。分享给大家供大家参考。具体实现方法如下:

我需要实现一个Windows下远程连接到SSH服务器执行命令的功能,所以就在网上找资料。我的环境是:Windows7 64位,Python 2.7 32位。按照网上的说法,需要下载pycrypto和paramiko两个模块进行安装。最后下载的版本是pycrypto2.3和paramiko1.7.6。
安装过程也比较简单,先安装pycrypto后安装paramiko,解压后在命令提示符下切换到解压后的目录,输入python setup.py install就可以了。另外安装pycrypto前需要先安装mingw,不然会因为缺少编译器而提示缺少一个BAT文件。安装好mingw后,需要在Python安装目录下的Libdistutils文件夹里建立一个distutils.cfg文件,文件内容为:
[build] compiler=mingw32

mingw的下载地址:http://sourceforge.net/projects/mingw/files/Automated%20MinGW%20Installer/mingw-get-inst/
pycrypto及paramiko的下载与安装请参考:《windows下安装python paramiko模块的代码

安装好以后就可以编写写代码了。由于我的SSH服务器只需要用户名和密码就可以连接,应该说属于最简单的一种了。

下面是一个例子,相信一看就懂了:
stdout.readlines()返回一个列表,一般来说,Linux命令的每行输出存储为一个元素,且已经带了换行符。

import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.8.248', 22, username='root', password='password', timeout=4)
stdin, stdout, stderr = client.exec_command('ls -l')
for std in stdout.readlines():
  print std,
client.close()
 

输出的结果为:

>>>
总计 184804
-rw------- 1 root root    973 05-19 20:27 anaconda-ks.cfg
-rw-r--r-- 1 root root   13895 05-19 20:27 install.log
-rw-r--r-- 1 root root   3058 05-19 20:25 install.log.syslog
-rw-r--r-- 1 root root 189008625 05-28 09:55 tmp
>>>
 


Python建立SSH连接就是这样,欢迎大家参考。。。。

python通过ssh实现服务器日志下载的方法介绍

python通过ssh实现服务器日志下载是如何来实现的呢?下面的内容将会通过具体的实例来演示python通过ssh实现服务器日志下载的实现方法及相关技巧:

本文实例讲述了python操作ssh实现服务器日志下载的方法。分享给大家供大家参考。具体实现方法如下:

#coding:utf-8
"""
  ssh操作例子 实现了服务器日志下载
  2012-08-24
  yywolf
"""
import paramiko
import time
hostname="&#63;&#63;&#63;&#63;"
port=22
username="app"
password="&#63;&#63;&#63;&#63;"
if __name__=="__main__":
#  paramiko.util.log.log_to_file('paramiko.log')
  s = paramiko.SSHClient()
  s.load_system_host_keys()
  s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  s.connect(hostname,port,username,password,timeout=4)
  stdin,stdout,stderr = s.exec_command("sh ~/log/check")
  print stdout.read()
  s.close()
  #sftp
  t = paramiko.Transport((hostname,port))
  t.connect(username=username,password=password)
  sftp = paramiko.SFTPClient.from_transport(t)
  files = sftp.listdir("/home/app/log/")
  for f in files:
    print f
  filetime = time.strftime('%Y-%m-%d',time.localtime(time.time()))
  #需要下载的文件 和下载后的文件名
  sftp.get("/home/app/log/server.txt","C:\Users\Administrator\Desktop\server.txt")
  sftp.get("/home/app/log/"+filetime+".log.zip","C:UsersAdministratorDesktop\"+filetime+".log.zip")
  #RASkey
  pkey_file = "E:\yy\tools\key\rsa.txt"
  key = paramiko.RSAKey.from_private_key_file(pkey_file)
  s = paramiko.SSHClient()
  s.load_system_host_keys()
  s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  s.connect(hostname,port,username,pkey=key)
  stdin, stdout, stderr = s.exec_command("ls -l /home/app/log")
  print stdout.read()
  s.close()
  raw_input()
 


python通过ssh实现服务器日志下载就是这样,欢迎大家参考。。。。

Python读写配置文件的方法介绍

Python读写配置文件的方法是如何来实现的呢?下面的内容将会通过具体的实例来演示Python读写配置文件的方法的实现方法及相关技巧:

本文实例讲述了Python读写配置文件的方法。分享给大家供大家参考。具体分析如下:

python 读写配置文件在实际应用中具有十分强大的功能,在实际的操作中也有相当简捷的操作方案,以下的文章就是对python 读写配置文件的具体方案的介绍,相信对大家学习Python有所帮助。

python 读写配置文件ConfigParser模块是python自带的读取配置文件的模块.通过他可以方便的读取配置文件. 这里就来简单介绍一下python 读写配置文件的方法.
配置文件.顾名思议就是存放配置信息的文件.下面是个例子

[info]
age = 21
name = chen
gender = male
 

其中[ ] 中的info是这段配置的名字下面age,name都是属性下面的代码演示了如何读取python 读写配置文件.和修改配置中变量的值

from __future__ import with_statement
import ConfigParser
config=ConfigParser.ConfigParser()
with open(''testcfg.cfg'',''rw'') as cfgfile:
config.readfp(cfgfile)
name=config.get(''info'',''name'')
age=config.get(''info'',''age'')
print name
print age
config.set(''info'',''gender'',''male'')
config.set(''info'',''age'',''21'')
age=config.get(''info'',''age'')
print name
print age
 

首先

config=ConfigParser.ConfigParser() 

得到一个配置config对象.下面打开一个配置文件 cfgfile. 用readfp()读取这个文件.这样配置的内容就读到config对象里面了.接下来一个问题是如何读取值.常用的方法是get() 和getint() . get()返回文本. getint()返回整数

name=config.get(''info'',''name'') 

意思就是.读取config中info段中的name变量值.最后讲讲如何设置值.使用set(段名,变量名,值) 来设置变量.config.set(”info”,”age”,”21”) 表示把info段中age变量设置为21. 就这么简单. 以上就是对python 读写配置文件的相关介绍。


Python读写配置文件的方法就是这样,欢迎大家参考。。。。

python处理二进制数据的方法介绍

python处理二进制数据的方法是如何来实现的呢?下面的内容将会通过具体的实例来演示python处理二进制数据的方法的实现方法及相关技巧:

本文实例讲述了python处理二进制数据的方法。分享给大家供大家参考。具体如下:

#!/usr/env/env python
#-*- coding: cp936 -*-
'''''
add Head Infomation for pcm file
'''
import sys
import struct
import os
__author__ = 'bob_hu, hewitt924@gmail.com'
__date__ = 'Dec 19,2011'
__update__ = 'Dec 19,2011'
def geneHeadInfo(sampleRate,bits,sampleNum):
  '''''
  生成头信息,需要采样率,每个采样的位数,和整个wav的采样的字节数
  '''
  rHeadInfo = 'x52x49x46x46'
  fileLength = struct.pack('i',sampleNum + 36)
  rHeadInfo += fileLength
  rHeadInfo += 'x57x41x56x45x66x6Dx74x20x10x00x00x00x01x00x01x00'
  rHeadInfo += struct.pack('i',sampleRate)
  rHeadInfo += struct.pack('i',sampleRate * bits / 8)
  rHeadInfo += 'x02x00'
  rHeadInfo += struct.pack('H',bits)
  rHeadInfo += 'x64x61x74x61'
  rHeadInfo += struct.pack('i',sampleNum)
  return rHeadInfo
if __name__ == '__main__':
  if len(sys.argv) != 5:
    print "usage: python %s inFile sampleRate bits outFile" % sys.argv[0]
    sys.exit(1)
  fout = open(sys.argv[4],'wb') #用二进制的写入模式
  #fout.write(struct.pack('4s','x66x6Dx74x20'))
  #写入一个长度为4的串,这个串的二进制内容为 66 6D 74 20
  #Riff_flag,afd,fad,afdd, = struct.unpack('4c',fin.read(4))
  #读入四个字节,每一个都解析成一个字母
  #open(sys.argv[4],'wb').write(struct.pack('4s','fmt '))
  #将字符串解析成二进制后再写入
  #open(sys.argv[4],'wb').write('x3Cx9Cx00x00x57')
  #直接写入二进制内容:3C 9C 00 00 57
  #fout.write(struct.pack('i',6000)) #写入6000的二进制形式
  #check whether inFile has head-Info
  fin = open(sys.argv[1],'rb')
  Riff_flag, = struct.unpack('4s',fin.read(4))
  if Riff_flag == 'RIFF':
    print "%s 有头信息" % sys.argv[1]
    fin.close()
    sys.exit(0)
  else:
    print "%s 没有头信息" % sys.argv[1]
    fin.close()
    #采样率
    sampleRate = int(sys.argv[2])
    #bit位
    bits = int(sys.argv[3])
    fin = open(sys.argv[1],'rb')
    startPos = fin.tell()
    fin.seek(0,os.SEEK_END)
    endPos = fin.tell()
    sampleNum = (endPos - startPos)
    print sampleNum
    headInfo = geneHeadInfo(sampleRate,bits,sampleNum)
    fout.write(headInfo)
    fin.seek(os.SEEK_SET)
    fout.write(fin.read())
    fin.close()
    fout.close()
 


python处理二进制数据的方法就是这样,欢迎大家参考。。。。

Python中使用paramiko模块实现ssh连接登录Linux服务器的方法介绍

Python中使用paramiko模块实现ssh连接登录Linux服务器是如何来实现的呢?下面的内容将会通过具体的实例来演示Python中使用paramiko模块实现ssh连接登录Linux服务器的实现方法及相关技巧:

要说清楚Python中的深浅拷贝,需要搞清楚下面一系列概念:
变量-引用-对象(可变对象,不可变对象)-切片-拷贝(浅拷贝,深拷贝)

【变量-对象-引用】

在Python中一切都是对象,比如说:3, 3.14, ‘Hello’, [1,2,3,4],{‘a’:1}……

甚至连type其本身都是对象,type对象
Python中变量与C/C++/Java中不同,它是指对象的引用,Python是动态类型,程序运行时候,会根据对象的类型
来确认变量到底是什么类型。

单独赋值: 比如说:

>>> a = 3
 

在运行a=3后,变量a变成了对象3的一个引用。在内部,变量事实上是到对象内存空间的一个指针

因为Python的变量不过是对象的引用,或指向对象的指针,因此在程序中可以经常改变变量引用

>>> x = 42      #变量绑定到整型对象
>>> x = 'Hello' #现在又成了字符串
>>> x = [1,2,3] #现在又成了列表
 

专业表述如下:

变量是一个系统表的元素,拥有指向对象的连接的空间
对象是被分配的一块内存,存储其所代表的值
引用是自动形成的从变量到对象的指针
特别注意: 类型属于对象,不是变量
比如像刚才的a=3, 整数对象3包含了两重信息
1.值为3
2.一个头部信息:告诉Pthyon,这是个整数对象[相当于一个指向int的指针]

共享引用: 比如说:

>>> a = 3
>>> b = a
 

在运行赋值语句b = a之后,变量a和变量b指向了同一个对象的内存空间.

从上图可以看到,a和b,其id完全一样,指向同一个整数对象3,或者说同一块内存

如果删掉a后, 不会影响b

拷贝概念的引入就是针对:可变对象的共享引用潜在的副作用而提出的.
【可变对象-不可变对象】
在Python中不可变对象指:一旦创建就不可修改的对象,包括字符串,元祖,数字
在Python中可变对象是指:可以修改的对象,包括:列表、字典
上面说的a,b都是整数,整数是不可变对象,如果是可变对象的话,就是另外一回事了。

>>> L1 = [2,3,4]      #L1变量指向的是一个可变对象:列表
>>> L2 = L1           #将L1值赋给L2后,两者共享引用同一个列表对象[1,2,3,4]
>>> L1[0] = 200       #因为列表可变,改变L1中第一个元素的值
>>> L1; L2            #改变后,L1,L2同时改变,因为对象本身值变了
[200, 3, 4]
[200, 3, 4]
 

如果不想改变列表L2的值,有两种方法:切片 和 copy模块

>>> L1 = [2,3,4]
>>> L2 = L1
>>> id(L1);id(L2)     #共享引用一个可变对象
45811784L
45811784L
>>> L2 = L1[:]        #切片操作
>>> id(L1);id(L2)     #切片后,对象就不一样了
45811784L
45806920L
>>> L1[0] = 200
>>> L1;L2             #L1发生改变,L2没有变化
[200, 3, 4]
[2,   3, 4]
 

【拷贝】
1. 切片技术应用于所有的序列,包括:列表、字符串、元祖
>>>但切片不能应用于字典。对字典只能使用D.copy()方法或D.deepcopy()方法.

2. 深浅拷贝,即可用于序列,也可用于字典

   >>> import copy
   >>> X = copy.copy(Y)      #浅拷贝:只拷贝顶级的对象,或者说:父级对象
   >>> X = copy.deepcopy(Y)  #深拷贝:拷贝所有对象,顶级对象及其嵌套对象。或者说:父级对象及其子对象
 

如果字典只有顶级对象:

如果字典中嵌套对象:

【结论】

深浅拷贝都是对源对象的复制,占用不同的内存空间
如果源对象只有一级目录的话,源做任何改动,不影响深浅拷贝对象
如果源对象不止一级目录的话,源做任何改动,都要影响浅拷贝,但不影响深拷贝
序列对象的切片其实是浅拷贝,即只拷贝顶级的对象


Python中使用paramiko模块实现ssh连接登录Linux服务器就是这样,欢迎大家参考。。。。

Python中的深拷贝和浅拷贝详细介绍

下面的内容主要介绍了Python中的深拷贝和浅拷贝,欢迎大家参考:

要说清楚Python中的深浅拷贝,需要搞清楚下面一系列概念:
变量-引用-对象(可变对象,不可变对象)-切片-拷贝(浅拷贝,深拷贝)

【变量-对象-引用】

在Python中一切都是对象,比如说:3, 3.14, ‘Hello’, [1,2,3,4],{‘a’:1}……

Python中的深拷贝和浅拷贝详细介绍
Python中的深拷贝和浅拷贝详细介绍

甚至连type其本身都是对象,type对象
Python中变量与C/C++/Java中不同,它是指对象的引用,Python是动态类型,程序运行时候,会根据对象的类型
来确认变量到底是什么类型。

单独赋值: 比如说:

>>> a = 3
 

在运行a=3后,变量a变成了对象3的一个引用。在内部,变量事实上是到对象内存空间的一个指针

因为Python的变量不过是对象的引用,或指向对象的指针,因此在程序中可以经常改变变量引用

>>> x = 42      #变量绑定到整型对象
>>> x = 'Hello' #现在又成了字符串
>>> x = [1,2,3] #现在又成了列表
 

专业表述如下:

变量是一个系统表的元素,拥有指向对象的连接的空间
对象是被分配的一块内存,存储其所代表的值
引用是自动形成的从变量到对象的指针
特别注意: 类型属于对象,不是变量
比如像刚才的a=3, 整数对象3包含了两重信息
1.值为3
2.一个头部信息:告诉Pthyon,这是个整数对象[相当于一个指向int的指针]

共享引用: 比如说:

>>> a = 3
>>> b = a
 

在运行赋值语句b = a之后,变量a和变量b指向了同一个对象的内存空间.

从上图可以看到,a和b,其id完全一样,指向同一个整数对象3,或者说同一块内存

如果删掉a后, 不会影响b

拷贝概念的引入就是针对:可变对象的共享引用潜在的副作用而提出的.
【可变对象-不可变对象】
在Python中不可变对象指:一旦创建就不可修改的对象,包括字符串,元祖,数字
在Python中可变对象是指:可以修改的对象,包括:列表、字典
上面说的a,b都是整数,整数是不可变对象,如果是可变对象的话,就是另外一回事了。

>>> L1 = [2,3,4]      #L1变量指向的是一个可变对象:列表
>>> L2 = L1           #将L1值赋给L2后,两者共享引用同一个列表对象[1,2,3,4]
>>> L1[0] = 200       #因为列表可变,改变L1中第一个元素的值
>>> L1; L2            #改变后,L1,L2同时改变,因为对象本身值变了
[200, 3, 4]
[200, 3, 4]
 

如果不想改变列表L2的值,有两种方法:切片 和 copy模块

>>> L1 = [2,3,4]
>>> L2 = L1
>>> id(L1);id(L2)     #共享引用一个可变对象
45811784L
45811784L
>>> L2 = L1[:]        #切片操作
>>> id(L1);id(L2)     #切片后,对象就不一样了
45811784L
45806920L
>>> L1[0] = 200
>>> L1;L2             #L1发生改变,L2没有变化
[200, 3, 4]
[2,   3, 4]
 

【拷贝】
1. 切片技术应用于所有的序列,包括:列表、字符串、元祖
>>>但切片不能应用于字典。对字典只能使用D.copy()方法或D.deepcopy()方法.

Python中的深拷贝和浅拷贝详细介绍
Python中的深拷贝和浅拷贝详细介绍

2. 深浅拷贝,即可用于序列,也可用于字典

   >>> import copy
   >>> X = copy.copy(Y)      #浅拷贝:只拷贝顶级的对象,或者说:父级对象
   >>> X = copy.deepcopy(Y)  #深拷贝:拷贝所有对象,顶级对象及其嵌套对象。或者说:父级对象及其子对象
 

如果字典只有顶级对象:

Python中的深拷贝和浅拷贝详细介绍
Python中的深拷贝和浅拷贝详细介绍

如果字典中嵌套对象:

Python中的深拷贝和浅拷贝详细介绍
Python中的深拷贝和浅拷贝详细介绍

【结论】

深浅拷贝都是对源对象的复制,占用不同的内存空间
如果源对象只有一级目录的话,源做任何改动,不影响深浅拷贝对象
如果源对象不止一级目录的话,源做任何改动,都要影响浅拷贝,但不影响深拷贝
序列对象的切片其实是浅拷贝,即只拷贝顶级的对象


Python中的深拷贝和浅拷贝就是这样,欢迎大家参考。。。。

python中通过ftplib模块实现FTP客户端的方法介绍

python中通过ftplib模块实现FTP客户端是如何来实现的呢?下面的内容将会通过具体的实例来演示python中通过ftplib模块实现FTP客户端的实现方法及相关技巧:

本文实例讲述了Python使用ftplib实现简易FTP客户端的方法。分享给大家供大家参考。具体实现方法如下:

#!/usr/bin/python
#-*- coding:utf-8 -*-
from ftplib import FTP   #加载ftp模块
ftp=FTP()          #设置变量
ftp.set_debuglevel(2)    #打开调试级别2,显示详细信息
ftp.connect("IP","port")  #连接的ftp sever和端口
ftp.login("user","password")#连接的用户名,密码
print ftp.getwelcome()   #打印出欢迎信息
ftp.cmd("xxx/xxx")     #更改远程目录
bufsize=1024        #设置的缓冲区大小
filename="filename.txt"   #需要下载的文件
file_handle=open(filename,"wb").write
#以写模式在本地打开文件
ftp.retrbinaly("RETR filename.txt",file_handle,bufsize)
#接收服务器上文件并写入本地文件
ftp.set_debuglevel(0)    #关闭调试模式
ftp.quit          #退出ftp
ftp.dir()          #显示目录下文件信息
ftp.mkd(pathname)      #新建远程目录
ftp.pwd()          #返回当前所在位置
ftp.rmd(dirname)      #删除远程目录
ftp.delete(filename)    #删除远程文件
ftp.rename(fromname, toname)#将fromname修改名称为toname。
ftp.storbinaly("STOR filename.txt",file_handel,bufsize) #上传目标文件
 

一个FTP完整实例:

#coding:utf-8
from ctypes import *
import os
import sys
import ftplib
class myFtp:
  ftp = ftplib.FTP()
  bIsDir = False
  path = ""
  def __init__(self, host, port='21'):
    self.ftp.set_debuglevel(2) #打开调试级别2,显示详细信息
    #self.ftp.set_pasv(0)  #0主动模式 1 #被动模式
    self.ftp.connect( host, port )
  def Login(self, user, passwd ):
    self.ftp.login( user, passwd )
    print self.ftp.welcome
  def DownLoadFile( self, LocalFile, RemoteFile ):
    file_handler = open( LocalFile, 'wb' )
    self.ftp.retrbinary( "RETR %s" %( RemoteFile ), file_handler.write )
    file_handler.close()
    return True
  def UpLoadFile( self, LocalFile, RemoteFile ):
    if os.path.isfile( LocalFile ) == False:
      return False
    file_handler = open( LocalFile, "rb" )
    self.ftp.storbinary( 'STOR %s'%RemoteFile, file_handler, 4096 )
    file_handler.close()
    return True
  def UpLoadFileTree( self, LocalDir, RemoteDir ):
    if os.path.isdir( LocalDir ) == False:
      return False
    LocalNames = os.listdir( LocalDir )
    print RemoteDir
    self.ftp.cwd( RemoteDir )
    for Local in LocalNames:
      src = os.path.join( LocalDir, Local)
      if os.path.isdir( src ):
        self.UpLoadFileTree( src, Local )
      else:
        self.UpLoadFile( src, Local )
    self.ftp.cwd( ".." )
    return
  def DownLoadFileTree( self, LocalDir, RemoteDir ):
    if os.path.isdir( LocalDir ) == False:
      os.makedirs( LocalDir )
    self.ftp.cwd( RemoteDir )
    RemoteNames = self.ftp.nlst()
    for file in RemoteNames:
      Local = os.path.join( LocalDir, file )
      if self.isDir( file ):
        self.DownLoadFileTree( Local, file )
      else:
        self.DownLoadFile( Local, file )
    self.ftp.cwd( ".." )
    return
  def show( self, list ):
    result = list.lower().split( " " )
    if self.path in result and "<dir>" in result:
      self.bIsDir = True
  def isDir( self, path ):
    self.bIsDir = False
    self.path = path
    #this ues callback function ,that will change bIsDir value
    self.ftp.retrlines( 'LIST', self.show )
    return self.bIsDir
  def close( self ):
    self.ftp.quit()
ftp = myFtp('********')
ftp.Login('*****','*****')
#ftp.DownLoadFile('TEST.TXT', 'others\runtime.log')#ok
#ftp.UpLoadFile('runtime.log', 'others\runtime.log')#ok
#ftp.DownLoadFileTree('bcd', 'others\abc')#ok
#ftp.UpLoadFileTree('aaa',"others\" )
ftp.close()
print "ok!"
 


python中通过ftplib模块实现FTP客户端就是这样,欢迎大家参考。。。。

python中的函数设计原则介绍

下面的内容主要介绍了python中的模块搜索和模块安装,欢迎大家参考:

在任何编程语言中,函数的应用主要出于以下两种情况:

1.代码块重复,这时候必须考虑用到函数,降低程序的冗余度
2.代码块复杂,这时候可以考虑用到函数,增强程序的可读性

当流程足够繁杂时,就要考虑函数,及如何将函数组合在一起。在Python中做函数设计,主要考虑到函数大小、聚合性、耦合性三个方面,这三者应该归结于规划与设计的范畴。高内聚、低耦合则是任何语言函数设计的总体原则。

1.如何将任务分解成更有针对性的函数从而导致了聚合性
2.如何设计函数间的通信则又涉及到耦合性
3.如何设计函数的大小用以加强其聚合性及降低其耦合性

【聚合】

每个函数只做一件事

完美的程序设计,每个函数应该而且只需做一件事。
比如说:把大象放进冰箱分三步:把门打开、把大象放进去、把门关上。
这样就应该写三个函数而不是一个函数拿所有的事全做了。这样结构清晰,层次分明,也好理解!

【大小】

保持简单、保持简短

Python即是面向过程的语言,也是面向对象的语言,但更多的是充当脚本语言的角色。
同样的功能,使用Python来实现其代码长度也许是C/C++/Java等语言的1/3. 几百行代码就能实现不小的功能!
如果项目中设计的一个函数需要翻页才能看完的话,就要考虑将函数拆分了。
在Python自带的200多个模块中,很少看到某个函数有两、三页的。
Python代码以简单明了著称,一个过长或者有着深层嵌套的函数往往成为设计缺陷的征兆。

【耦合】

输入使用参数、输出使用return语句

这样做可以让函数独立于它外部的东西。参数和return语句就是隔离外部依赖的最好的办法。

慎用全局变量

第一重考虑: 全局变量通常是一种蹩脚的函数间的进行通信的方式。
它会引发依赖关系和计时的问题,从而会导致程序调试和修改的困难。

第二重考虑: 从代码及性能优化来考虑,本地变量远比全局变量快。
根据Python对变量的搜索的先后顺序: 本地函数变量==》上层函数变量==》全局变量==》内置变量
从上面可以看出,本地变量优先被搜索,一旦找到,就此停下。下面专门对其做了测试,测试结果如下:

import profile
A = 5
def param_test():
  B = 5
  res = 0
  for i in range(100000000):
    res = B + i
  return res
if __name__=='__main__':
  profile.run('param_test()')
>>> ===================================== RESTART =====================================
>>>
     5 function calls in 37.012 seconds #全局变量测试结果:37 秒
  Ordered by: standard name
  ncalls tottime percall cumtime percall filename:lineno(function)
    1  19.586  19.586  19.586  19.586 :0(range)
    1  1.358  1.358  1.358  1.358 :0(setprofile)
    1  0.004  0.004  35.448  35.448 <string>:1(<module>)
    1  15.857  15.857  35.443  35.443 Learn.py:5(param_test)
    1  0.206  0.206  37.012  37.012 profile:0(param_test())
    0  0.000       0.000     profile:0(profiler)
>>> ===================================== RESTART =====================================
>>>
     5 function calls in 11.504 seconds  #局部变量测试结果: 11 秒
  Ordered by: standard name
  ncalls tottime percall cumtime percall filename:lineno(function)
    1  3.135  3.135  3.135  3.135 :0(range)
    1  0.006  0.006  0.006  0.006 :0(setprofile)
    1  0.000  0.000  11.497  11.497 <string>:1(<module>)
    1  8.362  8.362  11.497  11.497 Learn.py:5(param_test)
    1  0.000  0.000  11.504  11.504 profile:0(param_test())
    0  0.000       0.000     profile:0(profiler)
 

避免改变可变类型参数

Python数据类型比如说列表、字典属于可变对象。在作为参数传递给函数时,有时会像全局变量一样被修改。

这样做的坏处是:增强了函数之间的耦合性,从而导致函数过于特殊和不友好。维护起来也困难。

这个时候就要考虑使用切片S[:]和copy模块中的copy()函数和deepcopy()函数来做个拷贝,避免修改可变对象

具体参考这篇文章: Python中的深浅拷贝详解

避免直接改变另一个模块中的变量

比如说在b.py文件中导入a模块,a中有变量PI = 3.14, 但b.py想将其修改为:PI = 3.14159, 在这里你就搞不清楚变量PI原先的值到底是多少。碰到这种情况,可以考虑用易懂的函数名来实现:

#模块a.py
PI = 3.14
def setPi(new):
  PI = new
  return PI
 

这样既有自己想要的PI的值,又没有改变a模块中PI的值

import a
PI = a.setPi(3.14159)
print PI;a.PI
 


python中的模块搜索和模块安装就是这样,欢迎大家参考。。。。

python中的模块搜索和模块安装介绍

python中的模块搜索和模块安装是如何来实现的呢?下面的内容将会通过具体的实例来演示python中的模块搜索和模块安装的实现方法及相关技巧:

【import模块】

和C中的#include不同,Python中的import语句并不是简单的把一个文件插入另外一个文件。
导入其实是运行时的运算,程序第一次导入指定文件时,会执行以下步骤,

1. 找到模块文件
2. 编译成位码
3. 执行模块中的代码来创建所定义的模块

并生成.pyc字节码文件,这三个步骤只在程序执行时,模块第一次导入时会进行。之后导入相同的模块时,会跳过这三个步骤,而只提取内存中已加载的模块对象,速度要快的多。
NOTE:

1. Python把已加载的模块放在内置的sys.modules字典中,在import操作开始时会确认引用的模块是否已加载。如果想看哪些模块已加载,可以导入sys,打印sys.modules.keys()

>>> sys.modules.keys()
['heapq', 'functools', 'pyreadline.console.ansi',...,'pyreadline.modes']
 

2. 可以import的四种文件类型

1.源文件(.py)
2.字节码文件(.pyc)
3.C扩展文件(Windows: .dll或.pyd文件 | Linux: .so文件)
4.相同变量名的目录(用于包导入)

【搜索路径】

比如说:import math,不需要加路径和后缀名,系统会自动搜索路径,按照搜索先后顺序,列出模块搜索路径.

1. 程序的主目录(程序当前运行的目录)
2. PYTHONPATH目录(在环境变量里面配置与加到Path中一样)
3. 标准库目录(比如说: C:Python27Lib)
4. .pth文件所在内容(一般放在Libsite-packages目录下,如下:easy-install.pth)

import sys; sys.__plen = len(sys.path)
./setuptools-0.6c11-py2.7.egg
./py-1.4.26-py2.7.egg
./sphinx-1.3b1-py2.7.egg
./colorama-0.3.2-py2.7.egg
./babel-1.3-py2.7.egg
./snowballstemmer-1.2.0-py2.7.egg
./docutils-0.12-py2.7.egg
./pygments-2.0.1-py2.7.egg
./jinja2-2.7.3-py2.7.egg
./six-1.8.0-py2.7.egg
./pytz-2014.9-py2.7.egg
./markupsafe-0.23-py2.7.egg
./pyzmq-14.4.1-py2.7-win-amd64.egg
./tornado-4.0.2-py2.7-win-amd64.egg
./backports.ssl_match_hostname-3.4.0.2-py2.7.egg
./certifi-14.05.14-py2.7.egg
./egg-0.2.0-py2.7.egg
./chicken-0.1.0-py2.7.egg
import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new)
 

而所有这些路径可以通过sys.path来看到

>>> import sys
>>> sys.path
['', 'C:\Python27\lib\site-packages\setuptools-0.6c11-py2.7.egg', ...,'C:\Python27\lib\site-packages\wx-3.0-msw']
 

临时的工作路径加载,可以用

>>> sys.path.append('d:\test')
>>> sys.path
['', 'C:\Python27\lib\site-packages\setuptools-0.6c11-py2.7.egg', 'C:\Python27\lib\, 'd:\test']
>>> sys.path.remove('d:\test')
 

【模块安装】

但上面的方法只是临时性的,一旦退出程序或当前交互环境,就失效。要想永久生效就必须让其加入到上述目录中
Perl的强大在于CPAN,可喜的是,Python也开始有类似的技术及功能,比如说pip,可以用包括pip来安装模块。

1. 自写模块,直接拷贝到上述任意目录
2. 第三方模块,执行python setup.py install安装
3. 用easy_install安装

下载ez_setup.py文件
执行: python ez_setup.py
安装所要安装的模块: easy_install py

4. 用pip安装

先用easy_install pip命令来安装pip
再用pip install Markdown来安装具体模块,假设模块名为: Markdown

5. 用第三方模块管理库(比如说Canopy就可以管理科学计算模块,可惜很多需要收费)

python中的模块搜索和模块安装介绍
python中的模块搜索和模块安装介绍

用此工具,就可以安装ipython环境了

python中的模块搜索和模块安装介绍
python中的模块搜索和模块安装介绍


python中的模块搜索和模块安装就是这样,欢迎大家参考。。。。

python中装饰器的使用需要注意的地方

python中的装饰器是如何来使用的呢?下面的内容将会通过具体的实例来演示python中的装饰器的使用方法及相关技巧:

装饰器基本概念

大家都知道装饰器是一个很著名的设计模式,经常被用于 AOP (面向切面编程)的场景,较为经典的有插入日志,性能测试,事务处理,Web权限校验, Cache等。

Python 语言本身提供了装饰器语法(@),典型的装饰器实现如下:

  @function_wrapper
  def function():
    pass
 

@实际上是 python2.4 才提出的语法糖,针对 python2.4 以前的版本有另一种等价的实现:

  def function():
    pass
  function = function_wrapper(function)
 

装饰器的两种实现

函数包装器 – 经典实现

  def function_wrapper(wrapped):
    def _wrapper(*args, **kwargs):
      return wrapped(*args, **kwargs)
    return _wrapper
  @function_wrapper
  def function():
    pass
 

类包装器 – 易于理解

  class function_wrapper(object):
    def __init__(self, wrapped):
      self.wrapped = wrapped
    def __call__(self, *args, **kwargs):
      return self.wrapped(*args, **kwargs)
  @function_wrapper
  def function():
    pass
 

函数(function)自省

当我们谈到一个函数时,通常希望这个函数的属性像其文档上描述的那样,是被明确定义的,例如__name__ 和__doc__ 。

针对某个函数应用装饰器时,这个函数的属性就会发生变化,但这并不是我们所期望的。

  def function_wrapper(wrapped):
    def _wrapper(*args, **kwargs):
      return wrapped(*args, **kwargs)
    return _wrapper
  @function_wrapper
  def function():
    pass
  >>> print(function.__name__)
  _wrapper
 

python 标准库提供了functools.wraps(),来解决这个问题。

  import functools
  def function_wrapper(wrapped):
    @functools.wraps(wrapped)
    def _wrapper(*args, **kwargs):
      return wrapped(*args, **kwargs)
    return _wrapper
  @function_wrapper
  def function():
    pass
  >>> print(function.__name__)
  function
 

然而,当我们想要获取被包装函数的参数(argument)或源代码(source code)时,同样不能得到我们想要的结果。

  import inspect
  def function_wrapper(wrapped): ...
  @function_wrapper
  def function(arg1, arg2): pass
  >>> print(inspect.getargspec(function))
  ArgSpec(args=[], varargs='args', keywords='kwargs', defaults=None)
  >>> print(inspect.getsource(function))
    @functools.wraps(wrapped)
    def _wrapper(*args, **kwargs):
      return wrapped(*args, **kwargs)
 

包装类方法(@classmethod)

当包装器(@function_wrapper)被应用于@classmethod时,将会抛出如下异常:

  class Class(object):
    @function_wrapper
    @classmethod
    def cmethod(cls):
      pass
  Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "<stdin>", line 3, in Class
   File "<stdin>", line 2, in wrapper
   File ".../functools.py", line 33, in update_wrapper
    setattr(wrapper, attr, getattr(wrapped, attr))
  AttributeError: 'classmethod' object has no attribute '__module__'
 

因为@classmethod在实现时,缺少functools.update_wrapper需要的某些属性。这是functools.update_wrapper在 python2 中的 bug,3.2版本已被修复,参考 http://bugs.python.org/issue3445。

然而,在 python3 下执行,另一个问题出现了:

  class Class(object):
    @function_wrapper
    @classmethod
    def cmethod(cls):
      pass
  >>> Class.cmethod()
  Traceback (most recent call last):
   File "classmethod.py", line 15, in <module>
    Class.cmethod()
   File "classmethod.py", line 6, in _wrapper
    return wrapped(*args, **kwargs)
  TypeError: 'classmethod' object is not callable
 

这是因为包装器认定被包装的函数(@classmethod )是可以直接被调用的,但事实并不一定是这样的。被包装的函数实际上可能是描述符(descriptor ),意味着为了使其可调用,该函数(描述符)必须被正确地绑定到某个实例上。关于描述符的定义,可以参考 https://docs.python.org/2/howto/descriptor.html。
总结 – 简单并不意味着正确

尽管大家实现装饰器所用的方法通常都很简单,但这并不意味着它们一定是正确的并且始终能正常工作。

如同上面我们所看到的,functools.wraps() 可以帮我们解决__name__ 和__doc__ 的问题,但对于获取函数的参数(argument)或源代码( source code )则束手无策。


python中的装饰器就是这样,欢迎大家参考。。。。

python中推导式的使用方法介绍

python中的推导式是如何来实现的呢?下面的内容将会通过具体的实例来演示python中的推导式的实现方法及相关技巧:

推导式是Python中很强大的、很受欢迎的特性,具有语言简洁,速度快等优点。推导式包括:

1.列表推导式
2.字典推导式
3.集合推导式

嵌套列表推导式

NOTE: 字典和集合推导是最近才加入到Python的(Python 2.7 和Python 3.1以上版). 下面简要介绍下:

【列表推导式】

列表推导能非常简洁的构造一个新列表:只用一条简洁的表达式即可对得到的元素进行转换变形
其基本格式如下:

[expr for value in collection ifcondition]
 

过滤条件可有可无,取决于实际应用,只留下表达式;相当于下面这段for循环:

result = []
for value in collection:
    if condition:
        result.append(expression)
 

例1: 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母

>>> names = ['Bob','Tom','alice','Jerry','Wendy','Smith']
>>> [name.upper() for name in names if len(name)>3]
['ALICE', 'JERRY', 'WENDY', 'SMITH']
 

例2: 求(x,y)其中x是0-5之间的偶数,y是0-5之间的奇数组成的元祖列表

>>> [(x,y) for x in range(5) if x%2==0 for y in range(5) if y %2==1]
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]
 

例3: 求M中3,6,9组成的列表

>>> M = [[1,2,3],
...      [4,5,6],
...      [7,8,9]]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [row[2] for row in M]
[3, 6, 9]  

#或者用下面的方式
>>> [M[row][2] for row in (0,1,2)] [3, 6, 9]

python中的推导式就是这样,欢迎大家参考。。。。

python中列表的常用操作实例

python中列表作为5个最基本的数据类型之一,也是我们最常用的数据类型,本文将会介绍一些python中列表的常用操作,比如建立列表,删除,添加,过滤等操作:

本文实例讲述了python中list常用操作。分享给大家供大家参考。具体分析如下:

1.定义list

>>> li = ["a", "b", "mpilgrim", "z", "example"]
>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li[0]
'a'
>>> li[4]
'example'
 

2.负的list 索引

>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li[-1]
'example'
>>> li[-3]
'mpilgrim'
>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li[1:3]
['b', 'mpilgrim']
>>> li[1:-1]
['b', 'mpilgrim', 'z']
>>> li[0:3]
['a', 'b', 'mpilgrim']
 

3.向 list 中增加元素

>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li.append("new")
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new']
>>> li.insert(2, "new")
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new']
>>> li.extend(["two", "elements"])
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
 

4.搜索 list

>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
>>> li.index("example")
5
>>> li.index("new")
2
>>> li.index("c")
Traceback (innermost last):
 File "<interactive input>", line 1, in &#63;
ValueError: list.index(x): x not in list
>>> "c" in li
False
 

5.从 list 中删除元素

>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
>>> li.remove("z")
>>> li
['a', 'b', 'new', 'mpilgrim', 'example', 'new', 'two', 'elements']
>>> li.remove("new")
>>> li
['a', 'b', 'mpilgrim', 'example', 'new', 'two', 'elements']
>>> li.remove("c")
Traceback (innermost last):
 File "<interactive input>", line 1, in &#63;
ValueError: list.remove(x): x not in list
>>> li.pop()
'elements'
>>> li
['a', 'b', 'mpilgrim', 'example', 'new', 'two']
 

remove 从 list 中删除一个值的首次出现。
remove 仅仅 删除一个值的首次出现。 在这里, ‘new’ 在 list 中出现了两次, 但 li.remove(“new”) 只删除了 ‘new’ 的首次出现。
如果在 list 中没有找到值, Python 会引发一个异常来响应 index 方法。
pop 会做两件事: 删除 list 的最后一个元素, 然后返回删除元素的值。

6.list 运算符

>>> li = ['a', 'b', 'mpilgrim']
>>> li = li + ['example', 'new']
>>> li
['a', 'b', 'mpilgrim', 'example', 'new']
>>> li += ['two']
>>> li
['a', 'b', 'mpilgrim', 'example', 'new', 'two']
>>> li = [1, 2] * 3
>>> li
[1, 2, 1, 2, 1, 2]
 

7.使用join链接list成为字符串

>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> ["%s=%s" % (k, v) for k, v in params.items()]
['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
>>> ";".join(["%s=%s" % (k, v) for k, v in params.items()])
'server=mpilgrim;uid=sa;database=master;pwd=secret'
 

join 只能用于元素是字符串的 list; 它不进行任何的类型强制转换。连接一个存在一个或多个非字符串元素的 list 将引发一个异常。

8.分割字符串

>>> li = ['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
>>> s = ";".join(li)
>>> s
'server=mpilgrim;uid=sa;database=master;pwd=secret'
>>> s.split(";")
['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
>>> s.split(";", 1)
['server=mpilgrim', 'uid=sa;database=master;pwd=secret']
 

split 与 join 正好相反, 它将一个字符串分割成多元素 list。
注意, 分隔符 (“;”) 被完全去掉了, 它没有在返回的 list 中的任意元素中出现。
split 接受一个可选的第二个参数, 它是要分割的次数。

9.list的映射解析

>>> li = [1, 9, 8, 4]
>>> [elem*2 for elem in li]
[2, 18, 16, 8]
>>> li
[1, 9, 8, 4]
>>> li = [elem*2 for elem in li]
>>> li
[2, 18, 16, 8]
 

10.dictionary中的解析

>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> params.keys()
['server', 'uid', 'database', 'pwd']
>>> params.values()
['mpilgrim', 'sa', 'master', 'secret']
>>> params.items()
[('server', 'mpilgrim'), ('uid', 'sa'), ('database', 'master'), ('pwd', 'secret')]
>>> [k for k, v in params.items()]
['server', 'uid', 'database', 'pwd']
>>> [v for k, v in params.items()]
['mpilgrim', 'sa', 'master', 'secret']
>>> ["%s=%s" % (k, v) for k, v in params.items()]
['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
 

11.列表过滤

>>> li = ["a", "mpilgrim", "foo", "b", "c", "b", "d", "d"]
>>> [elem for elem in li if len(elem) > 1]
['mpilgrim', 'foo']
>>> [elem for elem in li if elem != "b"]
['a', 'mpilgrim', 'foo', 'c', 'd', 'd']
>>> [elem for elem in li if li.count(elem) == 1]
['a', 'mpilgrim', 'foo', 'c']
 


python中列表的常用操作就是这样,欢迎大家参考。。。。

python编程中遇到的错误和解决方法集锦

开个贴,用于记录平时经常碰到的Python的错误同时对导致错误的原因进行分析,并持续更新,方便以后查询,学习。
知识在于积累嘛!微笑
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
错误:

>>> def f(x, y):
    print x, y
>>> t = ('a', 'b')
>>> f(t)
Traceback (most recent call last):
  File "<pyshell#65>", line 1, in <module>
    f(t)
TypeError: f() takes exactly 2 arguments (1 given)
 

【错误分析】不要误以为元祖里有两个参数,将元祖传进去就可以了,实际上元祖作为一个整体只是一个参数,
实际需要两个参数,所以报错。必需再传一个参数方可.

>>> f(t, 'var2')
('a', 'b') var2
 

更常用的用法: 在前面加*,代表引用元祖

>>> f(*t)
'a', 'b'
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
错误:

>>> def func(y=2, x):
    return x + y
SyntaxError: non-default argument follows default argument
 

【错误分析】在C++,Python中默认参数从左往右防止,而不是相反。这可能跟参数进栈顺序有关。

>>> def func(x, y=2):
    return x + y
>>> func(1)
3
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

错误:

>>> D1 = {'x':1, 'y':2}
>>> D1['x']
1
>>> D1['z']
Traceback (most recent call last):
  File "<pyshell#185>", line 1, in <module>
    D1['z']
KeyError: 'z'
 

【错误分析】这是Python中字典键错误的提示,如果想让程序继续运行,可以用字典中的get方法,如果键存在,则获取该键对应的值,不存在的,返回None,也可打印提示信息.

>>> D1.get('z', 'Key Not Exist!')
'Key Not Exist!'
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

错误:

>>> from math import sqrt
>>> exec "sqrt = 1"
>>> sqrt(4)
Traceback (most recent call last):
  File "<pyshell#22>", line 1, in <module>
    sqrt(4)
TypeError: 'int' object is not callable
 

【错误分析】exec语句最有用的地方在于动态地创建代码字符串,但里面存在的潜在的风险,它会执行其他地方的字符串,在CGI中更是如此!比如例子中的sqrt = 1,从而改变了当前的命名空间,从math模块中导入的sqrt不再和函数名绑定而是成为了一个整数。要避免这种情况,可以通过增加in ,其中就是起到放置代码字符串命名空间的字典。

>>> from math import sqrt
>>> scope = {}
>>> exec "sqrt = 1" in scope
>>> sqrt(4)
2.0
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
错误:

>>> seq = [1, 2, 3, 4]
>>> sep = '+'
>>> sep.join(seq)
Traceback (most recent call last):
  File "<pyshell#25>", line 1, in <module>
    sep.join(seq)
TypeError: sequence item 0: expected string, int found
 

【错误分析】join是split的逆方法,是非常重要的字符串方法,但不能用来连接整数型列表,所以需要改成:

>>> seq = ['1', '2', '3', '4']
>>> sep = '+'
>>> sep.join(seq)
'1+2+3+4'
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

错误:

>>> print r'C:Program Filesfoobar'
SyntaxError: EOL while scanning string literal
 

【错误分析】Python中原始字符串以r开头,里面可以放置任意原始字符,包括,包含在字符中的不做转义。
但是,不能放在末尾!也就是说,最后一个字符不能是,如果真 需要的话,可以这样写:

>>> print r'C:Program Filesfoobar' "\"
C:Program Filesfoobar
>>> print r'C:Program Filesfoobar' + "\"
C:Program Filesfoobar
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
代码:

bad = 'bad'
try:
    raise bad
except bad:
    print 'Got Bad!'
 

错误:

>>>
Traceback (most recent call last):
  File "D:LearnPythonLearn.py", line 4, in <module>
    raise bad
TypeError: exceptions must be old-style classes or derived from BaseException, not str
 

【错误分析】因所用的Python版本2.7,比较高的版本,raise触发的异常,只能是自定义类异常,而不能是字符串。所以会报错,字符串改为自定义类,就可以了。

class Bad(Exception):
    pass
def raiseException():
    raise Bad()
try:
    raiseException()
except Bad:
    print 'Got Bad!'
  

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

class Super:
    def method(self):
        print "Super's method"
class Sub(Super):
    def method(self):
        print "Sub's method"
        Super.method()
        print "Over..."
S = Sub()
S.method()
 

执行上面一段代码,错误如下:

>>>
Sub's method
Traceback (most recent call last):
  File "D:LearnPythontest.py", line 12, in <module>
    S.method()
  File "D:LearnPythontest.py", line 8, in method
    Super.method()
TypeError: unbound method method() must be called with Super instance as first argument (got nothing instead)
 

【错误分析】Python中调用类的方法,必须与实例绑定,或者调用自身.

ClassName.method(x, 'Parm')
ClassName.method(self)
 

所以上面代码,要调用Super类的话,只需要加个self参数即可。

class Super:
    def method(self):
        print "Super's method"
class Sub(Super):
    def method(self):
        print "Sub's method"
        Super.method(self)
        print "Over..."
S = Sub()
S.method()
#输出结果
>>>
Sub's method
Super's method
Over...
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> reload(sys)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'sys' is not defined
 

【错误分析】reload期望得到的是对象,所以该模块必须成功导入。在没导入模块前,不能重载.

>>> import sys
>>> reload(sys)
<module 'sys' (built-in)>
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> def f(x, y, z):
    return x + y + z
>>> args = (1,2,3)
>>> print f(args)
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    print f(args)
TypeError: f() takes exactly 3 arguments (1 given)
 

【错误分析】args是一个元祖,如果是f(args),那么元祖是作为一个整体作为一个参数
*args,才是将元祖中的每个元素作为参数

>>> f(*args)
6
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> def f(a,b,c,d):
...   print a,b,c,d
...
>>> args = (1,2,3,4)
>>> f(**args)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() argument after ** must be a mapping, not tuple
 

【错误分析】错误原因**匹配并收集在字典中所有包含位置的参数,但传递进去的却是个元祖。
所以修改传递参数如下:

>>> args = {'a':1,'b':2,'c':3}
>>> args['d'] = 4
>>> f(**args)
1 2 3 4
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

python编程中遇到的错误和解决方法集锦
python编程中遇到的错误和解决方法集锦

【错误分析】在函数hider()内使用了内置变量open,但根据Python作用域规则LEGB的优先级:
先是查找本地变量==》模块内的其他函数==》全局变量==》内置变量,查到了即停止查找。
所以open在这里只是个字符串,不能作为打开文件来使用,所以报错,更改变量名即可。
可以导入__builtin__模块看到所有内置变量:异常错误、和内置方法

>>> import __builtin__
>>> dir(__builtin__)
['ArithmeticError', 'AssertionError', 'AttributeError',..
  .........................................zip,filter,map]
   

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

In [105]: T1 = (1)
In [106]: T2 = (2,3)
In [107]: T1 + T2
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-107-b105c7b32d90> in <module>()
----> 1 T1 + T2;
TypeError: unsupported operand type(s) for +: 'int' and 'tuple'
 

【错误分析】(1)的类型是整数,所以不能与另一个元祖做合并操作,如果只有一个元素的元祖,应该用(1,)来表示

In [108]: type(T1)
Out[108]: int
In [109]: T1 = (1,)
In [110]: T2 = (2,3)
In [111]: T1 + T2
Out[111]: (1, 2, 3)
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> hash(1,(2,[3,4]))
Traceback (most recent call last):
  File "<pyshell#95>", line 1, in <module>
    hash((1,2,(2,[3,4])))
TypeError: unhashable type: 'list'
 

【错误分析】字典中的键必须是不可变对象,如(整数,浮点数,字符串,元祖).
可用hash()判断某个对象是否可哈希

>>> hash('string')
-1542666171
 

但列表中元素是可变对象,所以是不可哈希的,所以会报上面的错误.
如果要用列表作为字典中的键,最简单的办法是:

>>> D = {}
>>> D[tuple([3,4])] = 5
>>> D
{(3, 4): 5}
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> L = [2,1,4,3]
>>> L.reverse().sort()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'sort'
>>> L
[3, 4, 1, 2]
 

【错误分析】列表属于可变对象,其append(),sort(),reverse()会在原处修改对象,不会有返回值,
或者说返回值为空,所以要实现反转并排序,不能并行操作,要分开来写

>>> L = [2,1,4,3]
>>> L.reverse()
>>> L.sort()
>>> L
[1, 2, 3, 4]
 

或者用下面的方法实现:

In [103]: sorted(reversed([2,1,4,3]))
Out[103]: [1, 2, 3, 4]
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> class = 78
SyntaxError: invalid syntax
 

【错误分析】class是Python保留字,Python保留字不能做变量名,可以用Class,或klass
同样,保留字不能作为模块名来导入,比如说,有个and.py,但不能将其作为模块导入

>>> import and
SyntaxError: invalid syntax
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> f = open('D:newtext.data','r')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 22] invalid mode ('r') or filename: 'D:newtext.data'
>>> f = open(r'D:newtext.data','r')
>>> f.read()
'Veryngoodnaaaaa'
 

【错误分析】n默认为换行,t默认为TAB键.
所以在D:目录下找不到ew目录下的ext.data文件,将其改为raw方式输入即可。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

try:
    print 1 / 0
except ZeroDivisionError:
    print 'integer division or modulo by zero'
finally:
    print 'Done'
else:
    print 'Continue Handle other part'
报错如下:
D:>python Learn.py
  File "Learn.py", line 11
    else:
       ^
SyntaxError: invalid syntax
 

【错误分析】错误原因,else, finally执行位置;正确的程序应该如下:

try:
    print 1 / 0
except ZeroDivisionError:
    print 'integer division or modulo by zero'
else:
    print 'Continue Handle other part'
finally:
    print 'Done'
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> [x,y for x in range(2) for y in range(3)]
  File "<stdin>", line 1
    [x,y for x in range(2) for y in range(3)]
           ^
SyntaxError: invalid syntax
 

【错误分析】错误原因,列表解析中,x,y必须以数组的方式列出(x,y)

>>> [(x,y) for x in range(2) for y in range(3)]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class JustCounter:
    __secretCount = 0
    def count(self):
        self.__secretCount += 1
        print 'secretCount is:', self.__secretCount
count1 = JustCounter()
count1.count()
count1.count()
count1.__secretCount
 

报错如下:

>>>
secretCount is: 1
secretCount is: 2
Traceback (most recent call last):
  File "D:LearnPythonLearn.py", line 13, in <module>
    count1.__secretCount
AttributeError: JustCounter instance has no attribute '__secretCount'
 

【错误分析】双下划线的类属性__secretCount不可访问,所以会报无此属性的错误.

解决办法如下:

# 1. 可以通过其内部成员方法访问
# 2. 也可以通过访问
ClassName._ClassName__Attr
#或
ClassInstance._ClassName__Attr
#来访问,比如:
print count1._JustCounter__secretCount
print JustCounter._JustCounter__secretCount
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> print x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> x = 1
>>> print x
1
 

【错误分析】Python不允许使用未赋值变量
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> t = (1,2)
>>> t.append(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'append'
>>> t.remove(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'remove'
>>> t.pop()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'pop'
 

【错误分析】属性错误,归根到底在于元祖是不可变类型,所以没有这几种方法.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> t = ()
>>> t[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: tuple index out of range
>>> l = []
>>> l[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range
 

【错误分析】空元祖和空列表,没有索引为0的项
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> if X>Y:
...  X,Y = 3,4
...   print X,Y
  File "<stdin>", line 3
    print X,Y
    ^
IndentationError: unexpected indent
>>>   t = (1,2,3,4)
  File "<stdin>", line 1
    t = (1,2,3,4)
    ^
IndentationError: unexpected indent
 

【错误分析】一般出在代码缩进的问题
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> f = file('1.txt')
>>> f.readline()
'AAAAAn'
>>> f.readline()
'BBBBBn'
>>> f.next()
'CCCCCn'
 

【错误分析】如果文件里面没有行了会报这种异常

>>> f.next() #
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
 

有可迭代的对象的next方法,会前进到下一个结果,而在一系列结果的末尾时,会引发StopIteration的异常.
next()方法属于Python的魔法方法,这种方法的效果就是:逐行读取文本文件的最佳方式就是根本不要去读取。
取而代之的用for循环去遍历文件,自动调用next()去调用每一行,且不会报错

for line in open('test.txt','r'):
    print line
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> string = 'SPAM'
>>> a,b,c = string
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
 

【错误分析】接受的变量少了,应该是

>>> a,b,c,d = string
>>> a,d
('S', 'M')
#除非用切片的方式
>>> a,b,c = string[0],string[1],string[2:]
>>> a,b,c
('S', 'P', 'AM')
或者
>>> a,b,c = list(string[:2]) + [string[2:]]
>>> a,b,c
('S', 'P', 'AM')
或者
>>> (a,b),c = string[:2],string[2:]
>>> a,b,c
('S', 'P', 'AM')
或者
>>> ((a,b),c) = ('SP','AM')
>>> a,b,c
('S', 'P', 'AM')
简单点就是:
>>> a,b = string[:2]
>>> c   = string[2:]
>>> a,b,c
('S', 'P', 'AM')
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> mydic={'a':1,'b':2}
>>> mydic['a']
1
>>> mydic['c']
Traceback (most recent call last):
  File "<stdin>", line 1, in &#63;
KeyError: 'c'
 

【错误分析】当映射到字典中的键不存在时候,就会触发此类异常, 或者可以,这样测试

>>> 'a' in mydic.keys()
True
>>> 'c' in mydic.keys()              #用in做成员归属测试
False
>>> D.get('c','"c" is not exist!')   #用get或获取键,如不存在,会打印后面给出的错误信息
'"c" is not exist!'
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

File "study.py", line 3
  return None
  ^
dentationError: unexpected indent
 

【错误分析】一般是代码缩进问题,TAB键或空格键不一致导致

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>>def A():
return A()
>>>A() #无限循环,等消耗掉所有内存资源后,报最大递归深度的错误
File "<pyshell#2>", line 2, in A return A()RuntimeError: maximum recursion depth exceeded
class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print "Ahaha..."
            self.hungry = False
        else:
            print "No, Thanks!"
 

该类定义鸟的基本功能吃,吃饱了就不再吃
输出结果:

>>> b = Bird()
>>> b.eat()
Ahaha...
>>> b.eat()
No, Thanks!
 

下面一个子类SingBird,

class SingBird(Bird):
    def __init__(self):
        self.sound = 'squawk'
    def sing(self):
        print self.sound
 

输出结果:

>>> s = SingBird()
>>> s.sing()
squawk
 

SingBird是Bird的子类,但如果调用Bird类的eat()方法时,

>>> s.eat()
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    s.eat()
  File "D:LearnPythonPerson.py", line 42, in eat
    if self.hungry:
AttributeError: SingBird instance has no attribute 'hungry'
 

【错误分析】代码错误很清晰,SingBird中初始化代码被重写,但没有任何初始化hungry的代码

class SingBird(Bird):
    def __init__(self):
        self.sound = 'squawk'
        self.hungry = Ture #加这么一句
    def sing(self):
        print self.sound
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print "Ahaha..."
            self.hungry = False
        else:
            print "No, Thanks!"
class SingBird(Bird):
    def __init__(self):
        super(SingBird,self).__init__()
        self.sound = 'squawk'
    def sing(self):
        print self.sound
>>> sb = SingBird()
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    sb = SingBird()
  File "D:LearnPythonPerson.py", line 51, in __init__
    super(SingBird,self).__init__()
TypeError: must be type, not classobj
 

【错误分析】在模块首行里面加上__metaclass__=type,具体还没搞清楚为什么要加

__metaclass__=type
class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print "Ahaha..."
            self.hungry = False
        else:
            print "No, Thanks!"
class SingBird(Bird):
    def __init__(self):
        super(SingBird,self).__init__()
        self.sound = 'squawk'
    def sing(self):
        print self.sound
>>> S = SingBird()
>>> S.
SyntaxError: invalid syntax
>>> S.
SyntaxError: invalid syntax
>>> S.eat()
Ahaha...
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> T
(1, 2, 3, 4)
>>> T[0] = 22
Traceback (most recent call last):
  File "<pyshell#129>", line 1, in <module>
    T[0] = 22
TypeError: 'tuple' object does not support item assignment
 

【错误分析】元祖不可变,所以不可以更改;可以用切片或合并的方式达到目的.

>>> T = (1,2,3,4)
>>> (22,) + T[1:]
(22, 2, 3, 4)
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

>>> X = 1;
>>> Y = 2;
>>> X + = Y
  File "<stdin>", line 1
    X + = Y
        ^
SyntaxError: invalid syntax
 

【错误分析】增强行赋值不能分开来写,必须连着写比如说 +=, *=

>>> X += Y
>>> X;Y
3
2
 


python编程中遇到的错误和解决方法就是这样,欢迎大家参考。。。。

python中如何以windows service的方式运行python程序

python中以windows service的方式运行python程序是如何来实现的呢?下面的内容将会通过具体的实例来演示python中以windows service的方式运行python程序的实现方法及相关技巧:

本文实例讲述了以windows service方式运行Python程序的方法。分享给大家供大家参考。具体实现方法如下:

#!/usr/bin/env python
# coding: utf-8
# SmallestService.py
#
# A sample demonstrating the smallest possible service written in Python.
import win32serviceutil
import win32service
import win32event
import time
class SmallestPythonService(win32serviceutil.ServiceFramework):
  _svc_name_ = "SmallestPythonService"
  _svc_display_name_ = "The smallest possible Python Service"
  def __init__(self, args):
    win32serviceutil.ServiceFramework.__init__(self, args)
    # Create an event which we will use to wait on.
    # The "service stop" request will set this event.
    self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
  def SvcStop(self):
    # Before we do anything, tell the SCM we are starting the stop process.
    self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
    # And set my event.
    win32event.SetEvent(self.hWaitStop)
  def SvcDoRun(self):
    #把你的程序代码放到这里就OK了
    f=open('d:\log.txt','w',0)
    f.write(time.ctime(time.time()))
    f.close()
    win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)
if __name__=='__main__':
  win32serviceutil.HandleCommandLine(SmallestPythonService)
  # 括号里的名字可以改成其他的,必须与class名字一致;
 


python中以windows service的方式运行python程序就是这样,欢迎大家参考。。。。

python中fileinput模块的使用方法

python中fileinput模块是如何来使用的呢?下面的内容将会通过具体的实例来演示python中fileinput模块的使用方法及相关技巧:

fileinput模块可以对一个或多个文件中的内容进行迭代、遍历等操作。
该模块的input()函数有点类似文件readlines()方法,区别在于:
前者是一个迭代对象,即每次只生成一行,需要用for循环迭代。
后者是一次性读取所有行。在碰到大文件的读取时,前者无疑效率更高效。
用fileinput对文件进行循环遍历,格式化输出,查找、替换等操作,非常方便。

【典型用法】

import fileinput
for line in fileinput.input():
    process(line)
 

【基本格式】

fileinput.input([files[, inplace[, backup[, bufsize[, mode[, openhook]]]]]])
 

【默认格式】

fileinput.input (files=None, inplace=False, backup='', bufsize=0, mode='r', openhook=None)
files:                  #文件的路径列表,默认是stdin方式,多文件['1.txt','2.txt',...]
inplace:                #是否将标准输出的结果写回文件,默认不取代
backup:                 #备份文件的扩展名,只指定扩展名,如.bak。如果该文件的备份文件已存在,则会自动覆盖。
bufsize:                #缓冲区大小,默认为0,如果文件很大,可以修改此参数,一般默认即可
mode:                   #读写模式,默认为只读
openhook:               #该钩子用于控制打开的所有文件,比如说编码方式等;
 

【常用函数】

fileinput.input()       #返回能够用于for循环遍历的对象
fileinput.filename()    #返回当前文件的名称
fileinput.lineno()      #返回当前已经读取的行的数量(或者序号)
fileinput.filelineno()  #返回当前读取的行的行号
fileinput.isfirstline() #检查当前行是否是文件的第一行
fileinput.isstdin()     #判断最后一行是否从stdin中读取
fileinput.close()       #关闭队列
 

【常见例子】

例子01: 利用fileinput读取一个文件所有行

>>> import fileinput
>>> for line in fileinput.input('data.txt'):
        print line,
#输出结果
Python
Java
C/C++
Shell
 

命令行方式:

#test.py
import fileinput
for line in fileinput.input():
    print fileinput.filename(),'|','Line Number:',fileinput.lineno(),'|: ',line
c:>python test.py data.txt
data.txt | Line Number: 1 |:  Python
data.txt | Line Number: 2 |:  Java
data.txt | Line Number: 3 |:  C/C++
data.txt | Line Number: 4 |:  Shell
 

例子02: 利用fileinput对多文件操作,并原地修改内容

#test.py
#---样本文件---
c:Python27>type 1.txt
first
second
c:Python27>type 2.txt
third
fourth
#---样本文件---
import fileinput
def process(line):
    return line.rstrip() + ' line'
for line in fileinput.input(['1.txt','2.txt'],inplace=1):
    print process(line)
#---结果输出---
c:Python27>type 1.txt
first line
second line
c:Python27>type 2.txt
third line
fourth line
#---结果输出---
 

命令行方式:

#test.py
import fileinput
def process(line):
    return line.rstrip() + ' line'
for line in fileinput.input(inplace = True):
    print process(line)
#执行命令
c:Python27>python test.py 1.txt 2.txt
 

例子03: 利用fileinput实现文件内容替换,并将原文件作备份

#样本文件:
#data.txt
Python
Java
C/C++
Shell
#FileName: test.py
import fileinput
for line in fileinput.input('data.txt',backup='.bak',inplace=1):
    print line.rstrip().replace('Python','Perl')  #或者print line.replace('Python','Perl'),
#最后结果:
#data.txt
Python
Java
C/C++
Shell
#并生成:
#data.txt.bak文件
 
#其效果等同于下面的方式
import fileinput
for line in fileinput.input():
    print 'Tag:',line,
#---测试结果:
d:>python Learn.py < data.txt > data_out.txt
 

例子04: 利用fileinput将CRLF文件转为LF

import fileinput
import sys
for line in fileinput.input(inplace=True):
    #将Windows/DOS格式下的文本文件转为Linux的文件
    if line[-2:] == "rn":
        line = line + "n"
    sys.stdout.write(line)
 

例子05: 利用fileinput对文件简单处理

#FileName: test.py
import sys
import fileinput
for line in fileinput.input(r'C:Python27info.txt'):
    sys.stdout.write('=> ')
    sys.stdout.write(line)
#输出结果
>>>
=> The Zen of Python, by Tim Peters
=>
=> Beautiful is better than ugly.
=> Explicit is better than implicit.
=> Simple is better than complex.
=> Complex is better than complicated.
=> Flat is better than nested.
=> Sparse is better than dense.
=> Readability counts.
=> Special cases aren't special enough to break the rules.
=> Although practicality beats purity.
=> Errors should never pass silently.
=> Unless explicitly silenced.
=> In the face of ambiguity, refuse the temptation to guess.
=> There should be one-- and preferably only one --obvious way to do it.
=> Although that way may not be obvious at first unless you're Dutch.
=> Now is better than never.
=> Although never is often better than *right* now.
=> If the implementation is hard to explain, it's a bad idea.
=> If the implementation is easy to explain, it may be a good idea.
=> Namespaces are one honking great idea -- let's do more of those!
 

例子06: 利用fileinput批处理文件

#---测试文件: test.txt test1.txt test2.txt test3.txt---
#---脚本文件: test.py---
import fileinput
import glob
for line in fileinput.input(glob.glob("test*.txt")):
    if fileinput.isfirstline():
        print '-'*20, 'Reading %s...' % fileinput.filename(), '-'*20
    print str(fileinput.lineno()) + ': ' + line.upper(),
#---输出结果:
>>>
-------------------- Reading test.txt... --------------------
1: AAAAA
2: BBBBB
3: CCCCC
4: DDDDD
5: FFFFF
-------------------- Reading test1.txt... --------------------
6: FIRST LINE
7: SECOND LINE
-------------------- Reading test2.txt... --------------------
8: THIRD LINE
9: FOURTH LINE
-------------------- Reading test3.txt... --------------------
10: THIS IS LINE 1
11: THIS IS LINE 2
12: THIS IS LINE 3
13: THIS IS LINE 4
 

例子07: 利用fileinput及re做日志分析: 提取所有含日期的行

#--样本文件--
aaa
1970-01-01 13:45:30  Error: **** Due to System Disk spacke not enough...
bbb
1970-01-02 10:20:30  Error: **** Due to System Out of Memory...
ccc
#---测试脚本---
import re
import fileinput
import sys
pattern = 'd{4}-d{2}-d{2} d{2}:d{2}:d{2}'
for line in fileinput.input('error.log',backup='.bak',inplace=1):
    if re.search(pattern,line):
        sys.stdout.write("=> ")
        sys.stdout.write(line)
#---测试结果---
=> 1970-01-01 13:45:30  Error: **** Due to System Disk spacke not enough...
=> 1970-01-02 10:20:30  Error: **** Due to System Out of Memory...
 

例子08: 利用fileinput及re做分析: 提取符合条件的电话号码

#---样本文件: phone.txt---
010-110-12345
800-333-1234
010-99999999
05718888888
021-88888888
#---测试脚本: test.py---
import re
import fileinput
pattern = '[010|021]-d{8}'  #提取区号为010或021电话号码,格式:010-12345678
for line in fileinput.input('phone.txt'):
    if re.search(pattern,line):
        print '=' * 50
        print 'Filename:'+ fileinput.filename()+' | Line Number:'+str(fileinput.lineno())+' | '+line,
#---输出结果:---
>>>
==================================================
Filename:phone.txt | Line Number:3 | 010-99999999
==================================================
Filename:phone.txt | Line Number:5 | 021-88888888
>>>
 

例子09: 利用fileinput实现类似于grep的功能

import sys
import re
import fileinput
pattern= re.compile(sys.argv[1])
for line in fileinput.input(sys.argv[2]):
    if pattern.match(line):
        print fileinput.filename(), fileinput.filelineno(), line
$ ./test.py import.*re *.py
#查找所有py文件中,含import re字样的
addressBook.py  2   import re
addressBook1.py 10  import re
addressBook2.py 18  import re
test.py         238 import re
 

例子10: 利用fileinput做正则替换

#---测试样本: input.txt
* [Learning Python](#author:Mark Lutz)
#---测试脚本: test.py
import fileinput
import re
for line in fileinput.input():
    line = re.sub(r'*
(.&#8727;)
#(.*)', r'<h2 id="2">1</h2>', line.rstrip())
    print(line)
#---输出结果:
c:Python27>python test.py input.txt
<h2 id="author:Mark Lutz">Learning Python</h2>
 

例子11: 利用fileinput做正则替换,不同字模块之间的替换

#---测试样本:test.txt
[@!$First]&[*%-Second]&[Third]
#---测试脚本:test.py
import re
import fileinput
regex = re.compile(r'^([^&]*)(&)([^&]*)(&)([^&]*)')
#整行以&分割,要实现[@!$First]与[*%-Second]互换
for line in fileinput.input('test.txt',inplace=1,backup='.bak'):
    print regex.sub(r'32145',line),
#---输出结果:
[*%-Second]&[@!$First]&[Third]
 

例子12: 利用fileinput根据argv命令行输入做替换

#---样本数据: host.txt
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
127.0.0.1      localhost
192.168.100.2  www.test2.com
192.168.100.3  www.test3.com
192.168.100.4  www.test4.com
#---测试脚本: test.py
import sys
import fileinput
source = sys.argv[1]
target = sys.argv[2]
files  = sys.argv[3:]
for line in fileinput.input(files,backup='.bak',openhook=fileinput.hook_encoded("gb2312")):
    #对打开的文件执行中文字符集编码
    line = line.rstrip().replace(source,target)
    print line
#---输出结果:
c:>python test.py 192.168.100 127.0.0 host.txt
#将host文件中,所有192.168.100转换为:127.0.0
127.0.0.1  localhost
127.0.0.2  www.test2.com
127.0.0.3  www.test3.com
127.0.0.4  www.test4.com
 


python中fileinput模块就是这样,欢迎大家参考。。。。

python中语句执行效率的测试方法

python中不同语句执行效率的测试方法是如何来实现的呢?下面的内容将会通过具体的实例来演示python中不同语句执行效率的测试方法的实现方法及相关技巧:

一个功能的实现,可以用多种语句来实现,比如说:while语句、for语句、生成器、列表推导、内置函数等实现,然而他们的效率并不一样。写了一个小程序来测试它们执行的效率。

测试内容:
将一个数字大小为20万的数字,依次取绝对值,放到列表中,测试重复1千次.
测试程序:

import time,sys
reps = 1000                #测试重复次数
nums = 200000              #测试时数字大小
def tester(func,*args):    #总体测试函数
    startTime = time.time()
    for i in range(reps):
        func(*args)
    elapsed = time.time() - startTime #用time模块来测试,结束时间与开始时间差
    return elapsed
def while_Statement():     #while循环实现
    res = []
    x   = 0
    while nums > x:
        x += 1
        res.append(abs(x))
def for_Statement():       #for循环实现
    res = []
    for x in range(nums):
        res.append(abs(x))
def generator_Expression():#生成器实现
    res = list(abs(x) for x in range(nums))
def list_Comprehension():  #列表解析实现
    res = [abs(x) for x in range(nums)]
def map_Function():        #内置函数map实现
    res = map(abs, range(nums))
print sys.version          #打印系统版本
tests = [while_Statement, for_Statement, generator_Expression, list_Comprehension, map_Function]
for testfunc in tests:     #将待测函数放置列表中依次遍历
    print testfunc.__name__.ljust(20),': ',tester(testfunc)  #
  

测试结果:

>>>
2.7.4 (default, Apr  6 2013, 19:55:15) [MSC v.1500 64 bit (AMD64)]
while_Statement      :  84.5769999027
for_Statement        :  75.2709999084
generator_Expression :  62.3519999981
list_Comprehension   :  60.4090001583
map_Function         :  47.5629999638
 

改写程序:

import sys
nums = 100
def while_Statement():
    res = []
    x   = 0
    while nums > x:
        x += 1
        res.append(abs(x))
def for_Statement():
    res = []
    for x in range(nums):
        res.append(abs(x))
def generator_Expression():
    res = list(abs(x) for x in range(nums))
def list_Comprehension():
    res = [abs(x) for x in range(nums)]
def map_Function():
    res = map(abs, range(nums))
if __name__=='__main__':
    import timeit            #用timeit模块来测试
    print sys.version
    funcs = [while_Statement, for_Statement, generator_Expression, list_Comprehension, map_Function]
    for func in funcs:
        print func.__name__.ljust(20),': ',timeit.timeit("func()", setup="from __main__ import func")
 

测试结果:

>>>
2.7.4 (default, Apr  6 2013, 19:55:15) [MSC v.1500 64 bit (AMD64)]
while_Statement      :  37.1800067428
for_Statement        :  30.3999109329
generator_Expression :  27.2597866441
list_Comprehension   :  17.386223449
map_Function         :  12.7386868963
 

测试分析:

用time模块,和timeit模块两种测试方式测试了很多组数字,得出的结果是执行内置函数最快,其次就是列表推导,再其次生成器和for循环,while循环最慢。一般最快的使用内置函数的方法要比使用最慢的while快两倍以上。简单分析下原因:内置函数比如说map,filter,reduce(在Python3.0中移除)基本上都是用C语言来实现的,所以速度是最快的,列表推导内的迭代在解释器内是以C语言的速度运行的(一般是for循环的两倍,对大型文件操作而言,用列表推导效果尤其明显),相比较for循环代码是在PVM步进运行要快的多。但for循环里面含range(),相对速度也会快些,while语句是纯粹用Python代码写成,所以速度最慢。所以函数式编程最好使用内置函数,然后才考虑使用列表推导或for循环。最好不用while循环.


python中不同语句执行效率的测试方法就是这样,欢迎大家参考。。。。

python中模拟和捕捉鼠标事件的方法介绍

python中模拟和捕捉鼠标事件的方法是如何来实现的呢?下面的内容将会通过具体的实例来演示python中模拟和捕捉鼠标事件的方法的实现方法及相关技巧:

本文实例讲述了Python捕捉和模拟鼠标事件的方法。分享给大家供大家参考。具体分析如下:

这个假期玩了不少galgame,不过有些很老的游戏没有自动运行模式,点击鼠标又太伤按键了,于是想把滚动鼠标滚轮映射为点击鼠标。

网上搜了一下,没发现什么现成的软件,而按键精灵又太重量级了,于是考虑干脆自己用Python写个算了。

这里需要把PyHook和PyWin32都装上(建议下exe版,免得安装时各种蛋疼)。

翻了翻教程,发现实现起来很简单:

# -*- coding: utf-8 -*-
import pythoncom, pyHook
def OnMouseEvent(event):
  print 'MessageName:',event.MessageName
  print 'Message:',event.Message
  print 'Time:',event.Time
  print 'Window:',event.Window
  print 'WindowName:',event.WindowName
  print 'Position:',event.Position
  print 'Wheel:',event.Wheel
  print 'Injected:',event.Injected
  print '---'
  # 返回 True 可将事件传给其它处理程序,否则停止传播事件
  return True
# 创建钩子管理对象
hm = pyHook.HookManager()
# 监听所有鼠标事件
hm.MouseAll = OnMouseEvent # 等效于hm.SubscribeMouseAll(OnMouseEvent)
# 开始监听鼠标事件
hm.HookMouse()
# 一直监听,直到手动退出程序
pythoncom.PumpMessages()
 

这个例子程序捕捉了所有的鼠标事件,实际上我只需要捕捉向下滚动滚轮的事件即可。翻了下文档,对应的是MouseWheel,之后只要判断event.Wheel是否为-1即可。

最后就是触发鼠标点击了,这就需要用到win32api.mouse_event()了,发送一个按下鼠标左键的事件,再发送弹起的事件,就完成一次单击了。

最终代码如下:

# -*- coding: utf-8 -*-
import pythoncom
import pyHook
import time
import win32api
import win32con
def onMouseWheel(event):
  if event.Wheel == -1:
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)
    time.sleep(0.05)
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)
  return True
hm = pyHook.HookManager()
hm.MouseWheel = onMouseWheel
hm.HookMouse()
pythoncom.PumpMessages()
 


python中模拟和捕捉鼠标事件的方法就是这样,欢迎大家参考。。。。

python中实现windwos系统中气泡提醒效果的方法

python中实现windwos系统中气泡提醒效果的方法是如何来实现的呢?下面的内容将会通过具体的实例来演示python中实现windwos系统中气泡提醒效果的方法的实现方法及相关技巧:

本文实例讲述了Python实现Windows上气泡提醒效果的方法。分享给大家供大家参考。具体实现方法如下:

# -*- encoding: gbk -*-
import sys
import os
import struct
import time
import win32con
from win32api import *
# Try and use XP features, so we get alpha-blending etc.
try:
 from winxpgui import *
except ImportError:
 from win32gui import *
class PyNOTIFYICONDATA:
 _struct_format = (
  "I" # DWORD cbSize; 结构大小(字节)
  "I" # HWND hWnd; 处理消息的窗口的句柄
  "I" # UINT uID; 唯一的标识符
  "I" # UINT uFlags;
  "I" # UINT uCallbackMessage; 处理消息的窗口接收的消息
  "I" # HICON hIcon; 托盘图标句柄
  "128s" # TCHAR szTip[128]; 提示文本
  "I" # DWORD dwState; 托盘图标状态
  "I" # DWORD dwStateMask; 状态掩码
  "256s" # TCHAR szInfo[256]; 气泡提示文本
  "I" # union {
    #  UINT uTimeout; 气球提示消失时间(毫秒)
    #  UINT uVersion; 版本(0 for V4, 3 for V5)
    # } DUMMYUNIONNAME;
  "64s" #  TCHAR szInfoTitle[64]; 气球提示标题
  "I" # DWORD dwInfoFlags; 气球提示图标
 )
 _struct = struct.Struct(_struct_format)
 hWnd = 0
 uID = 0
 uFlags = 0
 uCallbackMessage = 0
 hIcon = 0
 szTip = ''
 dwState = 0
 dwStateMask = 0
 szInfo = ''
 uTimeoutOrVersion = 0
 szInfoTitle = ''
 dwInfoFlags = 0
 def pack(self):
  return self._struct.pack(
   self._struct.size,
   self.hWnd,
   self.uID,
   self.uFlags,
   self.uCallbackMessage,
   self.hIcon,
   self.szTip,
   self.dwState,
   self.dwStateMask,
   self.szInfo,
   self.uTimeoutOrVersion,
   self.szInfoTitle,
   self.dwInfoFlags
  )
 def __setattr__(self, name, value):
  # avoid wrong field names
  if not hasattr(self, name):
   raise NameError, name
  self.__dict__[name] = value
class MainWindow:
 def __init__(self, title, msg, duration=3):
  # Register the Window class.
  wc = WNDCLASS()
  hinst = wc.hInstance = GetModuleHandle(None)
  wc.lpszClassName = "PythonTaskbarDemo"
  # 字符串只要有值即可,下面3处也一样
  wc.lpfnWndProc = { win32con.WM_DESTROY: self.OnDestroy }
  # could also specify a wndproc.
  classAtom = RegisterClass(wc)
  # Create the Window.
  style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU
  self.hwnd = CreateWindow(classAtom, "Taskbar Demo", style,
   0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT,
   0, 0, hinst, None
  )
  UpdateWindow(self.hwnd)
  iconPathName = os.path.abspath(os.path.join(sys.prefix, "pyc.ico"))
  icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE
  try:
   hicon = LoadImage(hinst, iconPathName, win32con.IMAGE_ICON, 0, 0, icon_flags)
  except:
   hicon = LoadIcon(0, win32con.IDI_APPLICATION)
  flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
  nid = (self.hwnd, 0, flags, win32con.WM_USER + 20, hicon, "Balloon tooltip demo")
  Shell_NotifyIcon(NIM_ADD, nid)
  self.show_balloon(title, msg)
  time.sleep(duration)
  DestroyWindow(self.hwnd)
 def show_balloon(self, title, msg):
  # For this message I can't use the win32gui structure because
  # it doesn't declare the new, required fields
  nid = PyNOTIFYICONDATA()
  nid.hWnd = self.hwnd
  nid.uFlags = NIF_INFO
  # type of balloon and text are random
  nid.dwInfoFlags = NIIF_INFO
  nid.szInfo = msg[:64]
  nid.szInfoTitle = title[:256]
  # Call the Windows function, not the wrapped one
  from ctypes import windll
  Shell_NotifyIcon = windll.shell32.Shell_NotifyIconA
  Shell_NotifyIcon(NIM_MODIFY, nid.pack())
 def OnDestroy(self, hwnd, msg, wparam, lparam):
  nid = (self.hwnd, 0)
  Shell_NotifyIcon(NIM_DELETE, nid)
  PostQuitMessage(0) # Terminate the app.
if __name__=='__main__':
 MainWindow("您有一条短消息", "您该睡觉了")
 


python中实现windwos系统中气泡提醒效果的方法就是这样,欢迎大家参考。。。。

python中找出某个文件中使用频率最高的汉字的方法

python中找出某个文件中使用频率最高的汉字的方法是如何来实现的呢?下面的内容将会通过具体的实例来演示python中找出某个文件中使用频率最高的汉字的方法的实现方法及相关技巧:

本文实例讲述了python简单获取本机计算机名和IP地址的方法。分享给大家供大家参考。具体实现方法如下:

方法一:

>>> import socket
>>> hostname = socket.gethostname()
>>> print hostname
china-43226208c
>>>ip = socket.gethostbyname(hostname)
>>>print ip
192.168.3.196
>>> ipList = socket.gethostbyname_ex(hostname)
>>> ipList
('china-43226208c', [], ['192.168.3.196'])
 

方法二:

>>> name = socket.getfqdn(socket.gethostname())
>>> name
'china-43226208c'
>>>
 


python中找出某个文件中使用频率最高的汉字的方法就是这样,欢迎大家参考。。。。

python调用IE浏览器打开网站页面的方法

python调用IE浏览器打开网站页面是如何来实现的呢?下面的内容将会通过具体的实例来演示python调用IE浏览器打开网站页面的实现方法及相关技巧:

本文实例讲述了python简单获取本机计算机名和IP地址的方法。分享给大家供大家参考。具体实现方法如下:

方法一:

>>> import socket
>>> hostname = socket.gethostname()
>>> print hostname
china-43226208c
>>>ip = socket.gethostbyname(hostname)
>>>print ip
192.168.3.196
>>> ipList = socket.gethostbyname_ex(hostname)
>>> ipList
('china-43226208c', [], ['192.168.3.196'])
 

方法二:

>>> name = socket.getfqdn(socket.gethostname())
>>> name
'china-43226208c'
>>>
 


python调用IE浏览器打开网站页面就是这样,欢迎大家参考。。。。

python中获取本机主机名和ip地址的方法

python中获取本机主机名和ip地址是如何来实现的呢?下面的内容将会通过具体的实例来演示python中获取本机主机名和ip地址的实现方法及相关技巧:

本文实例讲述了python简单获取本机计算机名和IP地址的方法。分享给大家供大家参考。具体实现方法如下:

方法一:

>>> import socket
>>> hostname = socket.gethostname()
>>> print hostname
china-43226208c
>>>ip = socket.gethostbyname(hostname)
>>>print ip
192.168.3.196
>>> ipList = socket.gethostbyname_ex(hostname)
>>> ipList
('china-43226208c', [], ['192.168.3.196'])
 

方法二:

>>> name = socket.getfqdn(socket.gethostname())
>>> name
'china-43226208c'
>>>
 


python中获取本机主机名和ip地址就是这样,欢迎大家参考。。。。

python中如何使用minidom读写xml格式的文件

python中使用minidom读写xml格式的文件是如何来实现的呢?下面的内容将会通过具体的实例来演示python中使用minidom读写xml格式的文件的实现方法及相关技巧:

本文实例讲述了Python使用minidom读写xml的方法。分享给大家供大家参考。具体分析如下:

一 python提供的xml支持

2种工业标准的xml解析方法-SAX和DOM。SAX(simple API for XML),是基于事件处理的,当XML文档顺序地读入时,每次遇到一个元素会触发相应的事件处理函数来处理。DOM(Document Object Model),通过构建一个树结构来表现整个xml文档,一旦树被构建,可以通过DOM提供了接口来遍历树和提取相应的数据。
python还提供了python独特的xml解析方法,相比于SAX和DOM更容易使用和更加快速,此方法为ElementTree。
python的xml模块为:

1)xml.dom.minidom
2)xml.elementtree
3)xml.sax + xml.dom

二 xml实例:(employees.xml)

<&#63;xml version="1.0" encoding="UTF-8" &#63;>
<employees>
 <employee>
  <name>l inux </name>
  <age> 30 </age>
 </employee>
 <employee>
  <name>windows </name>
  <age> 20 </age>
 </employee>
</employees>
 

三 使用xml.dom.minidom来读写xml
1)使用xml.dom.minidom来解析xml:

def TestMiniDom():
  from xml.dom import minidom
  doc = minidom.parse( "employees.xml" )
  # get root element: <employees/>
  root = doc.documentElement
  # get all children elements: <employee/> <employee/>
  employees = root.getElementsByTagName( "employee" )
  for employee in employees:
    print ( " ------------------------------------------- " )
    # element name : employee
    print (employee.nodeName)
    # element xml content : <employee><name>windows</name><age>20</age></employee>
    # basically equal to toprettyxml function
    print (employee.toxml())
    nameNode = employee.getElementsByTagName( "name" )[0]
    print (nameNode.childNodes)
    print (nameNode.nodeName +  ":"  + nameNode.childNodes[0].nodeValue)
    ageNode = employee.getElementsByTagName( "age" )[0]
    print (ageNode.childNodes)
    print (ageNode.nodeName +  ":"  + ageNode.childNodes[0].nodeValue)
    print ( " ------------------------------------------- " )
    for n in employee.childNodes:
      print (n)
TestMiniDom()
 

2)使用xml.dom.minidom来生成xml:

def CreateXml():
  import xml.dom.minidom
  impl = xml.dom.minidom.getDOMImplementation()
  dom = impl.createDocument(None, 'employees' , None)
  root = dom.documentElement
  employee = dom.createElement( 'employee' )
  root.appendChild(employee)
  nameE = dom.createElement( 'name' )
  nameT = dom.createTextNode( 'linux' )
  nameE.appendChild(nameT)
  employee.appendChild(nameE)
  ageE = dom.createElement( 'age' )
  ageT = dom.createTextNode( '30' )
  ageE.appendChild(ageT)
  employee.appendChild(ageE)
  f = open( 'employees2.xml' , 'w')
  dom.writexml(f, addindent = ' ' , newl = 'n' ,encoding = 'utf-8' )
  f.close()
CreateXml()
 

3)使用xml.dom.minidom需要注意的

*使用parse()或createDocument()返回的为DOM对象;
*使用DOM的documentElement属性可以获得Root Element;
*DOM为树形结构,包含许多的nodes,其中element是node的一种,可以包含子elements,textNode也是node的一种,是最终的子节点;
*每个node都有nodeName,nodeValue,nodeType属性,nodeValue是结点的值,只对textNode有效。对于textNode,想得到它的文本内容可以使用: .data属性。
*nodeType是结点的类型,现在有以下:
‘ATTRIBUTE_NODE”CDATA_SECTION_NODE”COMMENT_NODE”DOCUMENT_FRAGMENT_NODE’
‘DOCUMENT_NODE”DOCUMENT_TYPE_NODE”ELEMENT_NODE”ENTITY_NODE”ENTITY_REFERENCE_NODE’
‘NOTATION_NODE”PROCESSING_INSTRUCTION_NODE”TEXT_NODE’
*getElementsByTagName()可以根据名字来查找子elements;
*childNodes返回所有的子Nodes,其中所有的文本均为textNode,包含元素间的‘nr’和空格均为textNode;
*writexml() 时addindent=’ ‘表示子元素的缩进,newl=’n’表示元素间的换行,encoding=’utf-8’表示生成的xml的编码格式(<?xml version="1.0" encoding="utf-8"?>)。


python中使用minidom读写xml格式的文件就是这样,欢迎大家参考。。。。

python中DES算法加密和解密实例介绍

python中DES算法加密和解密是如何来实现的呢?下面的内容将会通过具体的实例来演示python中DES算法加密和解密的实现方法及相关技巧:

本文实例讲述了Python基于DES算法加密解密实现方法。分享给大家供大家参考。具体实现方法如下:

#coding=utf-8
from functools import partial
import base64
class DES(object):
  """
  DES加密算法
  interface: input_key(s, base=10), encode(s), decode(s)
  """
  __ip = [
    58,50,42,34,26,18,10,2,60,52,44,36,28,20,12,4,
    62,54,46,38,30,22,14,6,64,56,48,40,32,24,16,8,
    57,49,41,33,25,17, 9,1,59,51,43,35,27,19,11,3,
    61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7,
  ]
  __ip1 = [
    40,8,48,16,56,24,64,32,39,7,47,15,55,23,63,31,
    38,6,46,14,54,22,62,30,37,5,45,13,53,21,61,29,
    36,4,44,12,52,20,60,28,35,3,43,11,51,19,59,27,
    34,2,42,10,50,18,58,26,33,1,41, 9,49,17,57,25,
  ]
  __e = [
    32, 1, 2, 3, 4, 5,
    4 , 5, 6, 7, 8, 9,
    8 , 9,10,11,12,13,
    12,13,14,15,16,17,
    16,17,18,19,20,21,
    20,21,22,23,24,25,
    24,25,26,27,28,29,
    28,29,30,31,32, 1,
  ]
  __p = [
    16, 7,20,21,29,12,28,17,
    1 ,15,23,26, 5,18,31,10,
    2 ,8 ,24,14,32,27, 3, 9,
    19,13,30, 6,22,11, 4,25,
  ]
  __s = [
    [
    0xe,0x4,0xd,0x1,0x2,0xf,0xb,0x8,0x3,0xa,0x6,0xc,0x5,0x9,0x0,0x7,
    0x0,0xf,0x7,0x4,0xe,0x2,0xd,0x1,0xa,0x6,0xc,0xb,0x9,0x5,0x3,0x8,
    0x4,0x1,0xe,0x8,0xd,0x6,0x2,0xb,0xf,0xc,0x9,0x7,0x3,0xa,0x5,0x0,
    0xf,0xc,0x8,0x2,0x4,0x9,0x1,0x7,0x5,0xb,0x3,0xe,0xa,0x0,0x6,0xd,
    ],
    [
    0xf,0x1,0x8,0xe,0x6,0xb,0x3,0x4,0x9,0x7,0x2,0xd,0xc,0x0,0x5,0xa,
    0x3,0xd,0x4,0x7,0xf,0x2,0x8,0xe,0xc,0x0,0x1,0xa,0x6,0x9,0xb,0x5,
    0x0,0xe,0x7,0xb,0xa,0x4,0xd,0x1,0x5,0x8,0xc,0x6,0x9,0x3,0x2,0xf,
    0xd,0x8,0xa,0x1,0x3,0xf,0x4,0x2,0xb,0x6,0x7,0xc,0x0,0x5,0xe,0x9,
    ],
    [
    0xa,0x0,0x9,0xe,0x6,0x3,0xf,0x5,0x1,0xd,0xc,0x7,0xb,0x4,0x2,0x8,
    0xd,0x7,0x0,0x9,0x3,0x4,0x6,0xa,0x2,0x8,0x5,0xe,0xc,0xb,0xf,0x1,
    0xd,0x6,0x4,0x9,0x8,0xf,0x3,0x0,0xb,0x1,0x2,0xc,0x5,0xa,0xe,0x7,
    0x1,0xa,0xd,0x0,0x6,0x9,0x8,0x7,0x4,0xf,0xe,0x3,0xb,0x5,0x2,0xc,
    ],
    [
    0x7,0xd,0xe,0x3,0x0,0x6,0x9,0xa,0x1,0x2,0x8,0x5,0xb,0xc,0x4,0xf,
    0xd,0x8,0xb,0x5,0x6,0xf,0x0,0x3,0x4,0x7,0x2,0xc,0x1,0xa,0xe,0x9,
    0xa,0x6,0x9,0x0,0xc,0xb,0x7,0xd,0xf,0x1,0x3,0xe,0x5,0x2,0x8,0x4,
    0x3,0xf,0x0,0x6,0xa,0x1,0xd,0x8,0x9,0x4,0x5,0xb,0xc,0x7,0x2,0xe,
    ],
    [
    0x2,0xc,0x4,0x1,0x7,0xa,0xb,0x6,0x8,0x5,0x3,0xf,0xd,0x0,0xe,0x9,
    0xe,0xb,0x2,0xc,0x4,0x7,0xd,0x1,0x5,0x0,0xf,0xa,0x3,0x9,0x8,0x6,
    0x4,0x2,0x1,0xb,0xa,0xd,0x7,0x8,0xf,0x9,0xc,0x5,0x6,0x3,0x0,0xe,
    0xb,0x8,0xc,0x7,0x1,0xe,0x2,0xd,0x6,0xf,0x0,0x9,0xa,0x4,0x5,0x3,
    ],
    [
    0xc,0x1,0xa,0xf,0x9,0x2,0x6,0x8,0x0,0xd,0x3,0x4,0xe,0x7,0x5,0xb,
    0xa,0xf,0x4,0x2,0x7,0xc,0x9,0x5,0x6,0x1,0xd,0xe,0x0,0xb,0x3,0x8,
    0x9,0xe,0xf,0x5,0x2,0x8,0xc,0x3,0x7,0x0,0x4,0xa,0x1,0xd,0xb,0x6,
    0x4,0x3,0x2,0xc,0x9,0x5,0xf,0xa,0xb,0xe,0x1,0x7,0x6,0x0,0x8,0xd,
    ],
    [
    0x4,0xb,0x2,0xe,0xf,0x0,0x8,0xd,0x3,0xc,0x9,0x7,0x5,0xa,0x6,0x1,
    0xd,0x0,0xb,0x7,0x4,0x9,0x1,0xa,0xe,0x3,0x5,0xc,0x2,0xf,0x8,0x6,
    0x1,0x4,0xb,0xd,0xc,0x3,0x7,0xe,0xa,0xf,0x6,0x8,0x0,0x5,0x9,0x2,
    0x6,0xb,0xd,0x8,0x1,0x4,0xa,0x7,0x9,0x5,0x0,0xf,0xe,0x2,0x3,0xc,
    ],
    [
    0xd,0x2,0x8,0x4,0x6,0xf,0xb,0x1,0xa,0x9,0x3,0xe,0x5,0x0,0xc,0x7,
    0x1,0xf,0xd,0x8,0xa,0x3,0x7,0x4,0xc,0x5,0x6,0xb,0x0,0xe,0x9,0x2,
    0x7,0xb,0x4,0x1,0x9,0xc,0xe,0x2,0x0,0x6,0xa,0xd,0xf,0x3,0x5,0x8,
    0x2,0x1,0xe,0x7,0x4,0xa,0x8,0xd,0xf,0xc,0x9,0x0,0x3,0x5,0x6,0xb,
    ],
  ]
  __k1 = [
    57,49,41,33,25,17, 9,
    1 ,58,50,42,34,26,18,
    10, 2,59,51,43,35,27,
    19,11, 3,60,52,44,36,
    63,55,47,39,31,23,15,
    7 ,62,54,46,38,30,22,
    14, 6,61,53,45,37,29,
    21,13, 5,28,20,12, 4,
  ]
  __k2 = [
    14,17,11,24, 1, 5, 3,28,
    15, 6,21,10,23,19,12, 4,
    26, 8,16, 7,27,20,13, 2,
    41,52,31,37,47,55,30,40,
    51,45,33,48,44,49,39,56,
    34,53,46,42,50,36,29,32,
  ]
  __k0 = [
    1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
  ]
  __hex_bin = {
    '0':'0000','1':'0001','2':'0010','3':'0011',
    '4':'0100','5':'0101','6':'0110','7':'0111',
    '8':'1000','9':'1001','a':'1010','b':'1011',
    'c':'1100','d':'1101','e':'1110','f':'1111',
    ' ':'0000'
  }
  __re = lambda t, s: ''.join(s[i-1] for i in t)
  __IP = partial(__re, __ip)
  __IP1 = partial(__re, __ip1)
  __E = partial(__re, __e)
  __P = partial(__re, __p)
  __K1 = partial(__re, __k1)
  __K2 = partial(__re, __k2)
  __B = partial( lambda hex_bin, s: ''.join(hex_bin[w]
    for w in ''.join('%2x' % ord(w) for w in s))
    , __hex_bin)
  __DB = partial( lambda s: ''.join(chr(int(s[i:i+8], 2)) for i in range(0, len(s), 8)))
  __S = partial( lambda hex_bin, __s, s: ''.join(hex_bin['%x' % __s[i][
    int(s[i*6]+s[i*6+5], 2)*16 + int(s[i*6+1:i*6+5], 2)]] for i in range(8))
    , __hex_bin, __s)
  __F = partial( lambda s, k: ''.join('0' if s[i]==k[i] else '1' for i in range(len(s))))
  __K0 = partial( lambda k0, K2, k: map(K2,
    (k[k0[i]:28]+k[0:k0[i]] + k[k0[i]+28:56]+k[28:k0[i]+28] for i in range(16)))
    , __k0, __K2)
  __K = partial( lambda K1, K0, k: K0(K1(k))
    , __K1, __K0)
  def __init__(self):
    pass
  def input_key(self, key, base=10):
    if base == 2:
      pass
    elif base == 16:
      key = ''.join(self.__class__.__hex_bin[w] for w in key)
    else:
      key = self.__class__.__B(key)
    self.__k = self.__class__.__K(key)
  def __code(self, s, k):
    s = self.__IP(s)
    l, r = s[0:32], s[32:64]
    for i in range(16):
      r_t = r
      r = self.__E(r)
      r = self.__F(r, k[i])
      r = self.__S(r)
      r = self.__P(r)
      r = self.__F(r, l)
      l = r_t
    return self.__class__.__IP1(r+l)
  def encode(self, s):
    a = ''
    s += ' ' * ((8-len(s)%8)%8)
    for i in range(0, len(s), 8):
      before = self.__class__.__B(s[i:i+8])
      after = self.__code(before, self.__k)
      a += '%16x' % int(after, 2)
    return ''.join(w if w!=' ' else '0' for w in a)
  def decode(self, s):
    a = ''
    s.lower()
    for i in range(0, len(s), 16):
      before = ''.join(self.__class__.__hex_bin[s[j]] for j in range(i, i+16))
      after = self.__code(before, self.__k[::-1])
      a += self.__class__.__DB(after)
    return a.rstrip().decode('utf-8')
if __name__ == '__main__':
  d = DES()
  d.input_key('123456789')
  s = '再来一段中文'
  a = d.encode(s)
  print a
  b = d.decode(a)
  print b
 


python中DES算法加密和解密就是这样,欢迎大家参考。。。。

python中定时器wx.Timer的用法介绍

python中定时器wx.Timer是如何来实现的呢?下面的内容将会通过具体的实例来演示python中定时器wx.Timer的实现方法及相关技巧:

本文实例讲述了wxPython定时器wx.Timer简单应用。分享给大家供大家参考。具体如下:

# -*- coding: utf-8 -*-
########################################################
## 这是wxPython定时器wx.Timer的简单应用
## testwxTimer1.pyw
########################################################
import wx
import time
########################################################
class MyFrame1 ( wx.Frame ):
  def __init__( self, parent ):
    wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"测试定时器的小程序", pos = wx.DefaultPosition, size = wx.Size( 483,155 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
    self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
    self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INACTIVECAPTIONTEXT ) )
    gSizer1 = wx.GridSizer( 0, 2, 0, 0 )
    self.m_btnStart = wx.Button( self, wx.ID_ANY, u"启动定时器", wx.DefaultPosition, wx.DefaultSize, 0 )
    gSizer1.Add( self.m_btnStart, 0, wx.ALL, 5 )
    self.m_btnStop = wx.Button( self, wx.ID_ANY, u"停止定时器", wx.DefaultPosition, wx.DefaultSize, 0 )
    gSizer1.Add( self.m_btnStop, 0, wx.ALL, 5 )
    self.SetSizer( gSizer1 )
    self.Layout()
    self.m_statusBar1 = self.CreateStatusBar( 2, wx.ST_SIZEGRIP, wx.ID_ANY )
    self.Centre( wx.BOTH )
    # Connect Events
    self.m_btnStart.Bind( wx.EVT_BUTTON, self.OnStart )
    self.m_btnStop.Bind( wx.EVT_BUTTON, self.OnStop )
    # 创建定时器
    self.timer = wx.Timer(self)#创建定时器
    self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)#绑定一个定时器事件
  def __del__( self ):
    pass
  # Virtual event handlers, overide them in your derived class
  def OnStart( self, event ):
    self.timer.Start(1000)#设定时间间隔为1000毫秒,并启动定时器
  def OnStop( self, event ):
    self.timer.Stop()
  def OnTimer(self, evt):#显示时间事件处理函数
    t = time.localtime(time.time())
    StrYMDt = time.strftime("%Y-%B-%d", t)
    self.SetStatusText(StrYMDt,0) #显示年月日
    StrIMSt = time.strftime("%I:%M:%S", t)
    self.SetStatusText(StrIMSt,1)#显示时间
########################################################
## 以上界面代码使用wxFormBuilder自动创建
########################################################
if __name__=='__main__':
  app = wx.PySimpleApp()
  frame = MyFrame1(None)
  frame.Show()
  app.MainLoop()
########################################################
 

运行效果如下所示:


python中定时器wx.Timer就是这样,欢迎大家参考。。。。

python中获取不同操作系统硬件信息的方法

python中获取不同操作系统硬件信息是如何来实现的呢?下面的内容将会通过具体的实例来演示python中获取不同操作系统硬件信息的实现方法及相关技巧:

本文实例讲述了python获取各操作系统硬件信息的方法。分享给大家供大家参考。具体如下:

1. windows

使用WMI:

(WMI官网地址:http://pypi.python.org/pypi/WMI 或 点击此处本站下载。)

import wmi
w=wmi.WMI()
cpus=w.Win32_Processor()
for u in cpus:
  print 'cpu id:',u.ProcessorId
 

运行结果如下:

cpu id: BFEBFBFF0001067A
cpu id: BFEBFBFF0001067A
 

2. linux

直接读取:

/proc
文件下面的信息,都是些文本文件。如读取cpu信息:
/proc/cpuinfo

3. Mac

使用subprocess.Popen()

执行相应的命令:
/usr/sbin/system_profiler SPHardwareDataType
然后再得到输出分析结果


python中获取不同操作系统硬件信息就是这样,欢迎大家参考。。。。