转:SQLAIchem Tutorial

SQLAlchemy指南(tutorial)

对应版本: 0.3.4

目录

这个入门指导用于SQLAlchemy的快速入门,并便利SQLAlchemy的简单功能。如果你可以跳过这一部分进入 主文档 会涉及更多内容。如下的例子全部是在Python交互模式下完成了,并且全部通过了 doctest 测试。

1 安装

1.1 安装SQLAlchemy

setuptools 安装是非常简单的,只要运行如下命令即可:

# easy_install SQLAlchemy

这将会在Python Cheese Shop获取SQLAlchemy的最新版本并安装。或者你也可以使用setup.py安装一个发行包:

# python setup.py install

1.2 安装一个数据库API

SQLAlchemy被设计用于操作一个 DBAPI 实现,包括大多数常见的数据库。如果你有一个支持DBAPI的实现,那么可以跳入下一节。另外SQLite是一个易于使用的数据库,可以快速开始,并且他可以使用内存数据库。如果要使用SQLite,你将会需要:

  • pysqlite - SQLite的Python接口
  • SQLite函数库

注意在Windows下并不需要SQLite函数库,因为Windows版的pysqlite已经内含了。pysqlite和SQLite可以被安装到Linux或FreeBSD,通过预编译或从源码安装。

预编译包的地址为:

http://initd.org/tracker/pysqlite/wiki/PysqlitePackages

2 快速开始

2.1 导入

SQLAlchemy提供了完整的命名空间,只要导入sqlalchemy即可,无需其子包。为了方便使用本教程,我们导入所有命名到本地命名空间:

>>> from sqlalchemy import *

2.2 连接到数据库

导入之后,下一步是连接到需要的数据库,表现为(represent)为一个Engine对象。这个对象处理了连接的管理和特定数据库的操作。下面,我们连接SQLite基于文件的数据库”tutorial.db”

>>> db=create_engine("sqlite:///tutorial.db")

创建数据库引擎的更多信息查看”Database Engines”。

3 SQLAlchemy是两个库的包装

现在已经完成了安装和连接数据库,可以开始做点实际的事情了。但首先需要有些解释。

SQLAlchemy的核心有两个完全不同的功能,一个在另一个之上工作。一个是 SQL语言构造器 ,另一个是 ORM 。SQL语言构造器允许调用 ClauseElements 来构造SQL表达式。这些 ClauseElements 可以在编译成字符串并绑定到数据库后用于执行,并返回一个叫做 ResultProxy 的对象,类似于一个结果集对象,但是更象dbapi高版本的 cursor 对象。

ORM是建立在SQL语言构造器之上的工具集,用于将Python对象映射到数据库的行,提供了一系列接口用于从数据库中存取对象(行)。在ORM 工作时,在底层调用SQL语言构造器的API,这些通用的操作有些许的不同。不同的是,你不再使用行,而是使用自定义类的对象来操作。另外,数据库的查询 方式也不同,ORM的可以生成大多数的SQL查询,除此之外还可以在类中定义更多操作。

SA功能强大,无与伦比,只是有两个混合在一起的方法有些复杂。有效的使用SA的方法是先了解这两种不同的工具集,这是两个不同的概念,而大家常常 混交SQL语言构造器和ORM。关键的不同是,使用cursor形式的结果集时使用的是SQL语言构造器;而使用类实例进行管理时使用的是ORM。

本指南首先介绍SQL语言构造器,首先需要声明的数据库信息叫做 table metadata 。本指南包含了一些SQL构造的例子,包括如何有效的使用SQL语言构造器的例子。

4 操作数据库对象

在SQLAlchemy的核心哲学中表格和类是不同的。因为如此,SQLAlchemy提供了构造表格的方法(使用表格的元信息table metadata)。所以我们从构造表格的元信息对象和定制操作他们的对象开始。稍后我们可以看到SQLAlchemy的ORM,提供了表格元信息的高层 封装,允许我们随心所欲的装载和保存Python类。

4.1 定义元信息,绑定到引擎

首先,你的表格必须已经在MetaData集合中。我们将要创建简单(handy)表格的MetaData,并自动连接到引擎(将一个模式(schema)对象连接到引擎成为绑定binding):

>>> metadata=BoundMetaData(db)

一个构造BoundMetaData对象的等同方法是直接使用引擎URL,这将会帮我们调用 create_engine

>>> metadata=BoundMetaData("sqlite:///tutorial.db")

现在,我们告知metadata关于数据库中的表格,我们可以使用(issue)CREATE语句来创建表格,并且通过他们来创建和执行SQL语 句,除非需要打开和关闭任何连接。这都是自动完成的。注意这个功能是推荐使用的。SQLAlchemy包含了使用模式进行连接管理和SQL构造的全部功 能,并可以在任何引擎上进行操作。

本教程的目的,是教会大家使用”bound”对象,他可以使得代码简单和易读。

4.2 创建表格

使用metadata作为基本连接,我们可以创建表格:

>>> users_table=Table(‘user‘,metadata,
...     Column(‘user_id‘,Integer,primary_key=True),
...     Column(‘user_name‘,String(40)),
...     Column(‘password‘,String(10))
... )

有如你看到的,我们刚刚定义了一个叫做users的表格并拥有3个列:user_id作为主键,user_name和password。它现在只是 一个对象而与数据库中的表格没有必然联系。为了让表格生效,我们使用create()方法。有趣的是,我们可以让SQLAlchemy发送SQL语句到数 据库时同时显示SQL语句,只要设置BoundMetaData关联的Engine的echo选项即可:

>>> metadata.engine.echo=True
>>> users_table.create()
CREATE TABLE users (
    user_id INTEGER NOT NULL,
    user_name VARCHAR(40),
    password VARCHAR(10),
    PRIMARY KEY (user_id)
)
...

或者,如果users表格已经存在了(比如你第二次运行这些例子),在这种情况下你可以跳过create()方法的调用。你设置可以跳过列定义,而是让SQLAlchemy自动从数据库装入定义:

>>> users_table=Table(‘users‘,metadata,autoload=True)
>>> list(users_table.columns)[0].name
‘user_id‘

关于表格元信息的文档在”Database Meda Data”中。

4.3 插入记录

插入记录是通过表格对象的insert()方法实现的,这将会定义一个子句对象(clause object)(就是CluseElement)来代理INSERT语句:

>>> i=users_table.insert()
>>> i
<sqlalchemy.sql._Insert object at 0x...>
>>> print i
INSERT INTO users (user_id,user_name,password) VALUES (?,?,?)

当我们创建这个插入语句对象时,语句本身也绑定到了Engine,并已经可以执行了。子句对象的execute()方法将会将对象编译为特定引擎的SQL方言,并且执行语句:

>>> i.execute(user_name=‘Mary‘,password=‘secure‘)
INSERT INTO users (user_name,password) VALUES (?,?)
[‘Mary‘,‘secure‘]
COMMIT
<sqlalchemy.engine.base.ResultProxy object at 0x...>
>>> i.execute({‘user_name‘:‘Tom‘},{‘user_name‘:‘Fred‘},{‘user_name‘:‘Harry‘})
INSERT INTO users (user_name) VALUES (?)
[[‘Tom‘],[‘Fred‘],[‘Harry‘]]
COMMIT
<sqlalchemy.engine.base.ResultProxy object at 0x...>

注意VALUES子句会自动调整参数数量。这是因为ClauseElement的编译步骤并不依赖于特定的数据库,执行的参数也是如此。

当构造子句对象时,SQLAlchemy会绑定所有的值到参数。在构造时,参数绑定总是依靠键值对。在编译时,SQLAlchemy会转换他们到适当的格式,基于DBAPI的参数风格。这在DBAPI中描述的参数位置绑定中同样工作的很好。

这些文档继承于”Inserts”。

4.4 查询

我们可以检查users表中已经存在的数据。方法同插入的例子,只是你需要调用表格的select()方法:

>>> s=users_table.select()
>>> print s
SELECT users.user_id,users.user_name,users.password
FROM users
>>> r=s.execute()
SELECT users.user_id,users.user_name,users.password
FROM users
[]

这时,我们并没有忽略execute()的返回值。他是一个ResultProxy实例,保存了结果,而行为非常类似于DBAPI中的cursor对象:

>>> r
<sqlalchemy.engine.base.ResultProxy object at 0x...>
>>> r.fetchone()
(1,u‘Mary‘,u‘secure‘)
>>> r.fetchall()
[(2,u‘Tom‘,None),(3,u‘Fred‘,None),(4,u‘Harry‘,None)]

查询条件同Python表达式,使用Column对象。所有表达式中的Column对象都是ClauseElements的实例,例如Select、Insert和Table对象本身:

>>> r=users_table.select(users_table.c.user_name==‘Harry‘).execute()
SELECT users.user_id,users.user_name,users.password
FROM users
WHERE users.user_name=?
[‘Harry‘]
>>> row=r.fetchone()
>>> print row
(4,u‘Harry‘,None)

所幸的是所有标准SQL操作都可以用Python表达式来构造,包括连接(join)、排序(order)、分组(group)、函数 (function)、子查询(correlated subquery)、联合(union)等等。关于查询的文档”Simple Select”。

4.5 操作记录

你可以看到,当我们打印记录时返回的可执行对象,它以元组打印记录。这些记录实际上同时支持列表(list)和字典(dict)接口。字典接口允许通过字符串的列名定位字段,或者通过Column对象:

>>> row.keys()
[‘user_id‘,‘user_name‘,‘password‘]
>>> row[‘user_id‘],row[1],row[users_table.c.password]
(4,u‘Harry‘,None)

通过Column对象来定位是很方便的,因为这样避免了使用列名的方式。

结果集也是支持序列操作的。但是相对于select还有微小的差别,就是允许指定所选的列:

>>> for row in select([user_table.c.user_id,users_table.c.user_name]).execute():
...     print row
SELECT users.user_id,users.user_name
FROM users
[]
(1,u‘Mary‘)
... ...

4.6 表间关系

我们可以创建第二个表格,email_addresses,这会引用users表。定义表间的关联,使用ForeignKey构造。我们将来也会考虑使用表格的CREATE语句:

>>> email_addresses_table=Table(‘email_addresses‘,metadata,
...     Column(‘address_id‘,Integer,primary_key=True),
...     Column(‘email_address‘,String(100),nullable=False),
...     Column(‘user_id‘,Integer,ForeignKey(‘users.user_id‘)))
>>> email_addresses_table.create()
CREATE TABLE email_addresses (
    address_id INTEGER NOT NULL,
    email_address VARCHAR(100) NOT NULL,
    user_id INTEGER,
    PRIMARY KEY (address_id),
    FOREIGN KEY(user_id) REFERENCES users (user_id)
)
...

上面的email_addresses表与表users通过ForeignKey(’users.user_id’)相联系。ForeignKey 的构造器需要一个Column对象,或一个字符串代表表明和列名。当使用了字符串参数时,引用的表必须已经存在于相同的MetaData对象中,当然,可 以是另外一个表。

下面可以尝试插入数据:

>>> email_addresses_table.insert().execute(
...     {‘email_address‘:‘[email protected]‘,‘user_id‘:2},
...     {‘email_address‘:‘[email protected]‘,‘user_id‘:1})
INSERT INTO email_addresses (email_address,user_id) VALUES (?,?)
[[‘[email protected]‘,2],[‘[email protected]‘,1]]
COMMIT
<sqlalchemy.engine.base.ResultProxy object at 0x...>

在两个表之间,我们可以使用 join 方法构造一个连接:

>>> r=users_table.join(email_addresses_table).select().execute()
SELECT users.user_id, users.user_name, users.password,
email_addresses.address_id, email_addresses.email_address,
email_addresses.user_id
FROM users JOIN email_addresses ON users.user_id=email_addresses.user_id
[]
>>> print [row for row in r]
[(1, u‘Mary‘, u‘secure‘, 2, u‘[email protected]‘, 1),
(2,u‘Tom‘, None, 1, u‘[email protected]‘, 2)]

join 方法同时也是 sqlalchemy 命名空间中的一个独立的函数。连接条件指明了表对象给定的外键。条件(condition),也可以叫做 “ON 子句” ,可以被明确的指定,例如这个例子我们查询所有使用邮件地址作为密码的用户:

>>> print join(users_table, email_addresses_table,
...     and_(users_table.c.user_id==email_addresses_table.c.user_id,
...     users_table.c.password==email_addresses_table.c.email_address)
...     )
users JOIN email_addresses ON users.user_id=email_addresses.user_id AND
users.password=email_address.email_address

5 使用ORM工作

现在我们已经有了一些表格和SQL操作的知识了,让我们来看看SQLAlchemy的ORM (Object Relational Mapper) 。使用ORM,你可以将表格(和其他可以查询的对象)同Python联系起来,放入映射集(Mappers)当中。然后你可以执行查询并返回 对象实例 列表,而不是结果集。 对象实例 也被联系到一个叫做 Session 的对象,确保自动跟踪对象的改变,并可以使用 flush 立即保存结果。

5.1 创建一个映射

一个映射通常对应一个Python类,其核心意图是,“这个类的对象是用作这个表格的行来存储的”。让我们创建一个类叫做 User ,描述了一个用户对象,并保存到 users 表格。:

>>> class User(object):
...     def __repr__(self):
...         return "%s(%r,%r)"%(
...             self.__class__.__name__,self.user_name,self.password)

这个类是一个新形式(new style)的类(继承自 object )并且不需要构造器(在需要时默认提供)。我们只实现了一个 __repr__ 方法,用于显示 User 对象的基本信息。注意 __repr__ 方法应用了实例变量 user_namepassword ,这是还没定义的。我们可选的定义这些属性,并可以进行处理;SQLAlchemy的 Mapper 的构造器会自动管理这些,而且会自动协调到 users 表格的列名。让我们创建映射,并观察这些属性的定义:

>>> usermapper=mapper(User,users_table)
>>> ul=User()
>>> print ul.user_name
None
>>> print ul.password
None

函数 mapper 返回新建的 Mapper 实例。这也是我们为 User 类创建的第一个映射,也就是类的 主映射 。一般来说,不需要保存 usermapper 变量;SA的ORM会自动管理这个映射。

5.2 获取会话(Session)

创建了一个映射之后,所有对映射的操作都需要一个重要的对象叫做 Session 。所有对象通过映射的载入和保存都 必须 通过 Session 对象,有如对象的工作空间一样被加载到内存。特定对象在特定时间只能关联到一个 Session

缺省时,需要在载入和保存对象之前明确的创建 Session 对象。有多种方法来管理会话,但最简明的方法是调用 create_session()

>>> session=create_session()
>>> session
<sqlalchemy.orm.session.Session object at 0x...>

5.3 查询对象

会话对象拥有载入和存储对象的所有方法,同时也可以查看他们的状态。会话还提供了查询数据库的方便接口,你可以获取一个 Query 对象:

>>> query=session.query(User)
>>> print query.select_by(user_name=‘Harry‘)
SELECT users.user_name AS users_user_name, users.password AS users_password,
users.user_id AS users_user_id
FROM users
WHERE users.user_name=? ORDER BY users.oid
[‘Harry‘]
[User(u‘Harry‘,None)]

对象所有的查询操作实际上都是通过 Query 的。 Mapper 对象的多种 select 方法也是偷偷的在使用 Query 对象来执行操作。一个 Query 总是联系到一个特定的会话上。

让我们暂时关闭数据库回显,并尝试 Query 的几个方法。结尾是 _by 的方法主要用于对象的键参数。其他的方法允许接受 ClauseElement 对象,使用 Column 对象的Python表达式产生,同样的方法我们在上一节使用过。使用 ClauseElement 结构来查询更加冗长,但是更加灵活:

>>> metadata.engine.echo=False
>>> print query.select(User.c.user_id==3)
[User(u‘Fred‘,None)]
>>> print query.get(2)
User(u‘Tom‘,None)
>>> print query.get_by(user_name=‘Mary‘)
User(u‘Mary‘,u‘secure‘)
>>> print query.selectfirst(User.c.password==None)
User(u‘Tom‘,None)
>>> print query.count()
4

Note

User类有一个特别的属性 c ,这个属性描述了User映射表格对象的列。

User.c.user_name 等同于 users_table.c.user_name ,记得 User 是Python对象,而 usersTable 对象。

5.4 修改数据

作为小经验,我们看看如何做出修改。首先,创建一个新的用户”Ed”,然后加入会话:

>>> ed=User()
>>> ed.user_name=‘Ed‘
>>> ed.password=‘edspassword‘
>>> session.save(ed)
>>> ed in session
True

也可以修改数据库中的其他对象。使用 Query 对象载入,然后改变:

>>> mary=query.get_by(user_name=‘Mary‘)
>>> harry=query.get_by(user_name=‘Harry‘)
>>> mary.password=‘marysnewpassword‘
>>> harry.password=‘harrysnewpassword‘

这时,什么东西都没有保存到数据库;我们所有的修改都在内存中。如果这时程序其他部分尝试修改’Mary’会发生什么呢?因为使用相同的会话,所以再次载入’Mary’实际上定位到相同的主键’Mary’,并且 返回同一对象实例 。这个行为用在会话中确保数据库的一致性:

>>> mary2=query.get_by(user_name=‘Mary‘)
>>> mary is mary2
True

在唯一映射中,单一的会话可以确保安全的操作对象。

如果两个不同的会话同时操作一个对象,会检测到并发;SA会使用简单的并发控制来保存对象,可以选择使用拥有更强的使用ids的检查。参考 Mapper Arguments 了解更多细节。

5.5 保存

在新建了用户”ed”并对”Mary”和”Harry”作修改之后,我们再删除”Fred”

>>> fred=query.get_by(user_name=‘Fred‘)
>>> session.delete(fred)

然后发送更改到数据库,使用会话的 flush() 方法。开启回显来查看过程:

>>> metadata.engine.echo=True
>>> session.flush()
BEGIN
UPDATE users SET password=? WHERE users.user_id=?
[‘marysnewpassword‘,1]
UPDATE users SET password=? WHERE users.user_id=?
[‘harrysnewpassword‘,4]
INSERT INTO users (user_name,password) VALUES (?,?)
[‘Ed‘,‘edspassword‘]
DELETE FROM users WHERE users.user_id=?
[3]
COMMIT

5.6 关系

如果一个关系包含其他信息时,例如包含邮件地址的列表,我们可以在使用 relation() 创建 Mapper 时声明。当然,你还可以对这个关系作很多事情,我们举几个简单的例子。首先使用 users 表,它拥有一个外键关系连接到 email_addresses 表。 email_addresses 表中的每一行都有列 user_id 用来引用 users 表中的一行;而且 email_addresses 表中的多行可以引用 users 表中的同一行,这叫一对多关系。

首先,处理 email_addresses 表。我们创建一个新的类 Address 描述了 email_addresses 表中的一行,并且也创建了用于 Address 类的映射对象:

>>> class Address(object):
...     def __init__(self,email_address):
...         self.email_address=email_address
...     def __repr__(self):
...         return "%s(%r)"%(
...             self.__class__.__name__,self.email_address)
>>> mapper(Address, email_addresses_table)
<sqlalchemy.orm.mapper.Mapper object at 0x...>

然后,我们通过使用 relation() 创建一个关系连接 UserAddress 类,并且添加关系到 User 映射,使用 add_property 函数:

>>> usermapper.add_property(‘addresses‘,relation(Address))

函数 relation() 需要一个类或映射作为首参数,并且还有很多选项来控制行为。 User 映射现在给每一个 User 实例添加了一个属性叫 addresses 。SA将会自动检测这个一对多关系。并且随后创建 addresses 列表。当新的 User 对象创建时,这个列表为空 。

让我们看看数据库做了什么。当我们修改映射的配置时,最好清理一下会话,让所有载入的 User 对象可以重新载入:

>>> session.clear()

我们随之可以使用 User 对象的 addresses 属性来象列表一样处理:

>>> mary=query.get_by(user_name=‘Mary‘)
SELECT users.user_name AS users_user_name, users.password AS users_password,
users.user_id AS users_user_id
FROM users
WHERE users.user_name=? ORDER BY users.oid
LIMIT 1 OFFSET 0
[‘Mary‘]
>>> print [a for a in mary.address]
SELECT email_addresses.user_id AS email_address_user_id,
email_addresses.address_id AS email_addresses_address_id,
email_addresses.email_address AS email_addresses_email_address
FROM email_addresses
WHERE ?= email_addresses.user_id ORDER BY email_addresses.oid
[1]
[Address(u‘[email protected]‘)]

向列表添加元素也很简单。新的 Address 对象将会在调用会话的flush()时保存:

>>> mary.addresses.append(Address(‘[email protected]‘))
>>> session.flush()
BEGIN
INSERT INTO email_addresses (email_address,user_id) VALUEs (?,?)
[‘[email protected]‘,1]
COMMIT

主文档中关于使用映射的部分在如下地址:

http://www.sqlalchemy.org/docs/datamapping.myt#datamapping

5.7 事务

你可能已经注意到在上面例子中的 session.flush() ,SQLAlchemy使用 BEGINCOMMIT 来使用数据库事务。 flush() 方法使用事务来对一些记录执行一系列的指令。如果希望在 flush() 之外使用更大规模的事务,可以通过 SessionTransaction 对象,其生成使用 session.create_transaction() 。下面将会执行一个非常复杂的 SELECT 语句,进行大量的修改,然后再创建一个有两个邮箱的用户,这些都在事务中完成。而且将会在中间使用 flush() 来保存,然后在执行最后的 commit() 时将所有改变写入数据库。我们把事务封装在一个 try/except 语句块当中确保资源的安全释放:

>>> transaction=session.create_transaction()
>>> try:
...     (ed,harry,mary)=session.query(User).select(
...         User.c.user_name.in_(‘Ed‘,‘Harry‘,‘Mary‘),
...         order_by=User.c.user_name
...     )
...     del mary.address[1]
...     harry.addresses.append(Address(‘[email protected]‘))
...     session.flush()
...     print "***flushed the session***"
...     fred=User()
...     fred.user_name=‘fred_again‘
...     fred.addresses.append(Address(‘[email protected]‘))
...     fred.addresses.append(Address(‘[email protected]‘))
...     session.save(fred)
...     transaction.commit()
... except:
...     transaction.rollback()
...     raise
BEGIN
SELECT users.user_name AS users_user_name,
users.password AS users_password,
users.user_id AS users_user_id
FROM users
WHERE users.user_name IN (?, ?, ?) ORDER BY users.user_name
[‘Ed‘, ‘Harry‘, ‘Mary‘]
SELECT email_addresses.user_id AS email_addresses_user_id,
email_addresses.address_id AS email_addresses_address_id,
email_addresses.email_address AS email_addresses_email_address
FROM email_addresses
WHERE ? = email_addresses.user_id ORDER BY email_addresses.oid
[4]
UPDATE email_addresses SET user_id=? WHERE email_addresses.address_id = ?
[None, 3]
INSERT INTO email_addresses (email_address, user_id) VALUES (?, ?)
[‘[email protected]‘, 4]
***flushed the session***
INSERT INTO users (user_name, password) VALUES (?, ?)
[‘fred_again‘, None]
INSERT INTO email_addresses (email_address, user_id) VALUES (?, ?)
[‘[email protected]‘, 6]
INSERT INTO email_addresses (email_address, user_id) VALUES (?, ?)
[‘[email protected]‘, 6]
COMMIT

对应的主文档:

http://www.sqlalchemy.org/docs/unitofwork.myt#unitofwork

5.8 下一步

如上已经介绍了一下SQLAlchemy。但是不同的人可能有不同的做事方法,比如定义不同风格的映射的关系,所以还是允许使用原始的SQL来定义表格,还有Engine、SQL语句、数据库连接等。

链接:http://gashero.yeax.com/?p=6#id9

时间: 2024-09-19 12:30:27

转:SQLAIchem Tutorial的相关文章

初译 Support Vector Machines:A Simple Tutorial(一)

从本次开始我将开始尝试着逐章翻译一下 Alexey Nefedov的<Support Vector Machines:A Simple Tutorial>这本教材,这可是我们导师极力推荐的SVM教材,看了好久一直感觉一脸懵逼,索性开坑翻译一下吧,也当是加深理解,毕竟我也是一知半解,如果翻译的有不对的地方还望大佬们斧正,欢迎提意见,欢迎讨论. 嗯,就是这样. (一)Introduction 在本章节中将会介绍一些用于定义支持向量机(SVM)的基础的概念,这些概念对于理解SVM至关重要,假定读者了

ZetCode PyQt4 tutorial Dialogs

#!/usr/bin/python # -*- coding: utf-8 -*- """ ZetCode PyQt4 tutorial In this example, we receive data from a QtGui.QInputDialog dialog. author: Jan Bodnar website: zetcode.com last edited: October 2011 """ import sys from PyQ

简单的LESS Tutorial

1. 什么是LESS? LESS是一种动态的CSS语言,更专业的称呼是CSS preprocessor.作为CSS的扩展语言,LESS可以让CSS文件逻辑上更清晰,从而更容易维护和更新.LESS是开源的,诞生于2009年,采用javascript开发, LESS深受另外一种动态CSS语言SASS/SCSS的影响(SCSS是SASS的升级版) .相对于SASS/SCSS或者其他CSS preprocessor, LESS的典型特征有两个, 支持实时编译,例如网页或者应用可以直接应用less文件,通

(翻译)deeplearning.net/tutorial —— 栈式去噪自编码器(SdA)

前言 栈式去噪自编码器是栈式自动编码器的扩展[Bengio07],并且它在[Vincent08]里有介绍. 这次教程建立在之前的去噪自编码器Denoising Autoencoders.如果你对自编码器没什么了解,建议你先了解一下. 栈式自编码器 通过把上一层去噪自编码器找到的隐藏输入(output code)当作下一层的输入,我们可以把去噪自编码器以栈的形式构成一个深度网络.这种无监督预训练的结构在一层里同时实现.每一层当作一个去噪自编码器,通过重构输入(上一层的输出)最小化损失.一旦前面 层

A Complete ActiveX Web Control Tutorial

? Introduction ActiveX is a Microsoft technology developed in the mid 90's, that allows for the creation of applet-like applications that can be downloaded and run within Microsoft's Web browser. This article is intended for Visual C++ developers who

PIC32MZ tutorial -- OC Interrupt

In my previous blog "PIC32MZ tutorial -- Output Compare", I shows how to apply Output Compare without interrupt to generate PWM signal. I also tried the Output Compare interrupt. I selected OC to be PWM mode without fault pin (OCM = "110&qu

akka---Getting Started Tutorial (Java): First Chapter

原文地址:http://doc.akka.io/docs/akka/2.0.2/intro/getting-started-first-java.html Introduction Welcome to the first tutorial on how to get started with Akka and Java. We assume that you already know what Akka and Java are and will now focus on the steps

NS3之路---Tutorial解读---Beginning&amp;&amp;Concept

鉴于前面已经有写过了ns3安装的部分,因此也就不重新介绍beginning部分了. 第四章介绍了几个网络中非常重要的概念.对于网络比较熟悉的基本上一看就能懂,理解这几个概念对于理解ns3十分重要.下面就是tutorial第四章的相关翻译工作. 相关概念介绍 首先,在进行ns3程序开发之前,我们有必要对相关概念进行介绍.它们是网络中最基本的对象,因此必须理解. 节点-Node 在因特网术语中,连接到网络的计算设备被称为主机或者终端.但是由于ns3是网络模拟器,而非因特网模拟器,因此我们更习惯使用图

ZetCode PyQt4 tutorial signals and slots

#!/usr/bin/python # -*- coding: utf-8 -*- """ ZetCode PyQt4 tutorial In this example, we connect a signal of a QtGui.QSlider to a slot of a QtGui.QLCDNumber. author: Jan Bodnar website: zetcode.com last edited: October 2011 ""&quo