SQLAlchemy–一些常见问题
常见问题
在我们深入 SQLAlchemy 之前,让我们回答一系列关于 ORM 的问题:
- 能否阻止 SQLAlchemy 自动创建模式?相反,可以将 SQLAlchemy 模型绑定到现有的模式吗?
- 与编写原始 SQL 相比,使用 SQLAlchemy 时有没有性能开销?如果有,多少?
- 如果您没有足够的权限在数据库中创建表,SQLAlchemy 会抛出异常吗?
- 模式是如何修改的?它是自动完成的还是你写代码来完成的?
- 有没有对触发器的支持?
在这篇文章中,我们将回答所有的问题。一些问题将被详细讨论,而另一些问题将在另一篇文章中被总结和讨论。
SQLAlchemy 架构反射/自省
我们也可以指示一个Table对象从数据库中已经存在的相应数据库模式对象中加载关于自身的信息,而不是像前面的文章中所示的那样,使用Base.metadata.create_all(engine)从 SQLAlchemy 中自动创建一个模式。
让我们创建一个示例 sqlite3 数据库,其中一个表person存储一条记录:
import sqlite3
conn = sqlite3 . connect(" example . db ")
c = conn . cursor()
c . execute(' '
创建表人
(姓名文本,邮件文本)
' ' ')
c . execute(" INSERT INTO person VALUES(' John ',' John @ example . com '))"
c . close()
现在我们可以使用Table构造函数中的参数autoload和autoload_with来反映表person的结构。
>>> from sqlalchemy import create_engine, MetaData, Table
>>>
>>> engine = create_engine('sqlite:///example.db')
>>> meta = MetaData(bind=engine)
>>> person = Table("person", meta, autoload=True, autoload_with=engine)
>>> person
Table('person', MetaData(bind=Engine(sqlite:///example.db)), Column(u'name', TEXT(), table=), Column(u'email', TEXT(), table=), schema=None)
>>> [c.name for c in person.columns]
[u'name', u'email']
我们还可以使用MetaData.reflect方法反映数据库中的所有表。
>>> meta = MetaData()
>>> meta.reflect(bind=engine)
>>> person = meta.tables['person']
>>> person
Table(u'person', MetaData(bind=None), Column(u'name', TEXT(), table=), Column(u'email', TEXT(), table=), schema=None)
尽管反射非常强大,但它也有其局限性。记住反射构造Table元数据只使用关系数据库中可用的信息是很重要的。当然,这样的过程不能恢复实际上没有存储在数据库中的模式的某些方面。不可用的方面包括但不限于:
- 使用
Column构造函数的default关键字定义的客户端默认值、Python 函数或 SQL 表达式。 - 列信息,在
Column.info字典中定义。 Column或Table的.quote设定值。- 特定
Sequence与给定Column的关联。
SQLAlchemy 最近的改进允许反映视图、索引和外键选项等结构。像检查约束、表注释和触发器这样的结构没有被反映出来。
SQLAlchemy 的性能开销
由于 SQLAlchemy 在将变更(即session.commit())同步到数据库时使用工作单元模式,因此它不仅仅是像在原始 SQL 语句中那样“插入”数据。它跟踪对会话对象所做的更改,并维护所有对象的标识映射。它还执行相当数量的簿记,并维护任何 CRUD 操作的完整性。总的来说,工作单元自动化了将复杂对象图持久化到关系数据库中的任务,而无需编写显式的过程性持久化代码。当然,如此先进的自动化是有代价的。
因为 SQLAlchemy 的 ORM 不是为处理批量插入而设计的,所以我们可以写一个例子来测试它对原始 SQL 的效率。除了批量插入测试用例的 ORM 和原始 SQL 实现,我们还实现了一个使用 SQLAlchemy 核心系统的版本。由于 SQLAlchemy 的核心是原始 SQL 之上的一个抽象薄层,我们希望它能达到与原始 SQL 相当的性能水平。
import time
import sqlite3
from sqlalchemy . ext . declarative import declarative _ base
from sqlalchemy import Column,Integer,String,create _ engine
from sqlalchemy . ORM import scoped _ session,sessionmaker
base = declarative _ base()
session = scoped _ session(session maker())
类 User(Base):
_ _ tablename _ _ = " User "
id = Column(Integer,primary _ key = True)
name = Column(String(255))
def init _ db(dbname = ' SQLite:///example . db '):
engine = create _ engine(dbname,echo = False)
session . remove()
session . configure(bind = engine,autoflush=False,expire _ on _ commit = False)
base . metadata . drop _ all(engine)
base . metadata . create _ all(engine)
返回引擎
def test _ SQLAlchemy _ ORM(number _ of _ records = 100000):
init _ db()
start = time . time()
for I in range(number _ of _ records):
User = User()
User . NAME = ' NAME '+str(I)
session . add(User)
session . commit()
end = time . time()
print " SQLAlchemy ORM:在{1}秒内插入{0}条记录"。格式(
str(记录数),str(结束-开始)
)
def test _ sqlalchemy _ core(number _ of _ records = 100000):
engine = init _ db()
start = time . time()
engine . execute(
User。__ 表 _ _。insert(),
[{ " NAME ":" NAME "+str(I)} for I in range(number _ of _ records)]
)
end = time . time()
打印“SQLAlchemy Core:在{1}秒内插入{0}条记录”。格式(
str(记录数),str(结束-开始)
)
def init _ sqlite3(dbname = " sqlite3 . db "):
conn = sqlite3 . connect(dbname)
cursor = conn . cursor()
cursor . execute(" DROP TABLE IF EXISTS user ")
cursor . execute(" CREATE TABLE user(id INTEGER NOT NULL,name VARCHAR(255),PRIMARY KEY(id))"
conn . commit()
return conn
def test _ sqlite3(number _ of _ records = 100000):
conn = init _ sqlite3()
cursor = conn . cursor()
start = time . time()
for I in range(number _ of _ records):
cursor . execute(" INSERT INTO user(name)VALUES(?)",(" NAME " + str(i),))
conn . commit()
end = time . time()
打印" sqlite3:Insert { 0 } records in { 1 } seconds "。格式(
str(记录数),str(结束-开始)
)
if _ _ name _ _ = = " _ _ main _ _ ":
test _ sqlite3()
test _ sqlalchemy _ core()
test _ sqlalchemy _ ORM()
在前面的代码中,我们比较了使用原始 SQL、SQLAlchemy 的 Core 和 SQLAlchemy 的 ORM 向 sqlite3 数据库中批量插入 100000 条用户记录的性能。如果您运行该代码,您将得到类似如下的输出:
$ python orm_performance_overhead.py
sqlite3: Insert 100000 records in 0.226176977158 seconds
SQLAlchemy Core: Insert 100000 records in 0.371157169342 seconds
SQLAlchemy ORM: Insert 100000 records in 10.1760079861 seconds
注意,核心和原始 SQL 获得了相当的插入速度,而 ORM 比其他两个慢得多。尽管看起来 ORM 会导致很大的性能开销,但是请记住,只有当有大量数据需要插入时,开销才会变得很大。由于大多数 web 应用程序在一个请求-响应周期中运行小的 CRUD 操作,由于额外的便利和更好的可维护性,最好使用 ORM 而不是核心。
SQLAlchemy 和数据库权限
到目前为止,我们的示例在 sqlite3 数据库中运行良好,该数据库没有细粒度的访问控制,如用户和权限管理。如果我们想在 MySQL 或 PostgreSQL 中使用 SQLAlchemy 怎么办?当连接到数据库的用户没有足够的权限创建表、索引等时会发生什么??SQLAlchemy 会抛出数据库访问异常吗?
让我们用一个例子来测试当用户没有足够的权限时 SQLAlchemy 的 ORM 的行为。首先,我们创建一个测试数据库“test_sqlalchemy”和一个测试用户“sqlalchemy”。
$ psql
postgres=# create database test_sqlalchemy;
CREATE DATABASE
postgres=# create user sqlalchemy with password 'sqlalchemy';
CREATE ROLE
postgres=# grant all on database test_sqlalchemy to sqlalchemy;
GRANT
目前,测试用户“sqlalchemy”拥有对测试数据库“test_sqlalchemy”的所有访问权限。因此,我们希望数据库初始化调用成功,并将一条记录插入数据库“test_sqlalchemy”。
import time
import sqlite3
from sqlalchemy . ext . declarative import declarative _ base
from sqlalchemy import Column,Integer,String,create _ engine
from sqlalchemy . ORM import scoped _ session,sessionmaker
base = declarative _ base()
session = scoped _ session(session maker())
类 User(Base):
_ _ tablename _ _ = " User "
id = Column(Integer,primary _ key = True)
name = Column(String(255))
def init _ db(dbname):
engine = create _ engine(dbname,echo = False)
session . configure(bind = engine,autoflush=False,expire _ on _ commit = False)
base . metadata . create _ all(engine)
return engine
if _ _ name _ _ = = " _ _ main _ _ ":
init _ db(" PostgreSQL://sqlalchemy:sqlalchemy @ localhost/test _ sqlalchemy ")
u = User(name = " other _ User ")
session . add(u)
session . commit()
session . close()
执行完脚本后,您可以检查“user”表中是否有新的`User`记录。
$ psql test_sqlalchemy
psql (9.3.3)
Type “help” for help.
test _ sqlalchemy = # select * from " user ";
id |姓名
1 |其他 _ 用户
现在假设我们取消测试用户“sqlalchemy”的插入权限。那么我们应该预料到运行相同的代码将会失败并出现异常。
inside a psql shell
test_sqlalchemy=# revoke INSERT on “user” from sqlalchemy;
REVOKE
inside a bash shell
$ python permission_example.py
trace back(最近一次调用 last):
文件“permission _ example . py”,第 32 行,在
session.commit()
文件“/home/vagger/python central/local/lib/python 2.7/site-packages/sqlalchemy/ORM/scoping . py”,第 149 行,在 do
返回 getattr(self.registry(),name)(*args,**kwargs)
文件“/home…
File "/home/vagger/python central/local/lib/python 2.7/site-packages/sqlalchemy/engine/default . py ",第 425 行,在 do _ execute
cursor . execute(statement,parameters)
sqlalchemy . exc . programming error:(programming error)对关系用户的权限被拒绝
’ INSERT INTO " user “(name)VALUES(%)(name)s)返回” user "。id’ {‘name’: ‘other_user’}
如您所见,抛出了一个异常,表明我们没有权限将记录插入到关系用户中。
SQLAlchemy 的模式迁移
至少有两个库可用于执行 SQLAlchemy 迁移:`migrate` [文档链接](https://sqlalchemy-migrate.readthedocs.org/en/latest/ "documentation link")和`alembic` [文档链接](http://alembic.readthedocs.org/en/latest/ "documentation link")。
由于`alembic`是 SQLAlchemy 的作者写的,并且是积极开发的,所以我们推荐你用它来代替`migrate`。`alembic`不仅允许您手动编写迁移脚本,它还提供了自动生成脚本的方法。我们将在另一篇文章中进一步探讨如何使用`alembic`。
SQLAlchemy 对触发器的支持
可以使用定制的 DDL 结构创建 SQL 触发器,并与 SQLAlchemy 的事件挂钩。虽然它不是对触发器的直接支持,但它很容易实现并插入到任何系统中。我们将在另一篇文章中研究自定义 DDL 和事件。
提示和总结
在本文中,我们从 SQL 数据库管理员的角度回答了一些关于 SQLAlchemy 的常见问题。虽然 SQLAlchemy 默认为您创建一个数据库模式,但是它也允许您反映现有的模式并为您生成`Table`对象。使用 SQLAlchemy 的 ORM 时会有性能开销,但在执行批量插入时这一点最明显,而大多数 web 应用程序执行相对较小的 CRUD 操作。如果您的数据库用户没有足够的权限在表上执行某些操作,SQLAlchemy 将抛出一个异常,显示您无法执行这些操作的确切原因。SQLAlchemy 有两个迁移库,强烈推荐使用`alembic`。尽管不直接支持触发器,但是您可以很容易地在原始 SQL 中编写它们,并使用自定义 DDL 和 SQLAlchemy 事件将它们连接起来。
SQLAlchemy ORM 示例
ORM 摘要
在以前的一篇文章中,我们简要地浏览了一个带有两个表department和employee的示例数据库,其中一个部门可以有多个雇员,一个雇员可以属于任意数量的部门。我们使用了几个代码片段来展示 SQLAlchemy 表达式语言的强大功能,并展示如何编写 ORM 查询。
在本文中,我们将更详细地了解 SQLAlchemy 的 ORM,并找出如何更有效地使用它来解决现实世界中的问题。
部门和员工
我们将继续使用前一篇文章中的 department-employee 作为本文中的示例数据库。我们还将向每个表中添加更多的列,以使我们的示例更加有趣。
from sqlalchemy import Column, DateTime, String, Integer, ForeignKey, func
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
类 Department(Base):
_ _ tablename _ _ = ' Department '
id = Column(Integer,primary _ key = True)
name = Column(String)
class Employee(Base):
_ _ tablename _ _ = ' Employee '
id = Column(Integer,primary _ key = True)
name = Column(String)
# Use default = func . now()将雇员的默认雇佣时间
#设置为创建
# Employee 记录的当前时间
hired_on = Column(DateTime,default = func . now())
Department _ id = Column(Integer,foreign key(' Department . id ')
#雇员的当前时间
从 sqlalchemy 导入 create _ engine
engine = create _ engine(' SQLite:///ORM _ in _ detail . SQLite ')
从 sqlalchemy.orm 导入 session maker
session = session maker()
session . configure(bind = engine)
base . metadata . create _ all(engine)
注意,我们对 employee 表做了两处修改:1。我们插入了一个新列‘hired _ on ’,它是一个日期时间列,存储雇员被雇用的时间和,2。我们在关系Employee.department的backref中插入了一个关键字参数‘cascade ’,其值为 delete,all’。cascade 允许 SQLAlchemy 在部门本身被删除时自动删除该部门的雇员。
现在让我们写几行代码来使用新的表定义。
>>> d = Department(name="IT")
>>> emp1 = Employee(name="John", department=d)
>>> s = session()
>>> s.add(d)
>>> s.add(emp1)
>>> s.commit()
>>> s.delete(d) # Deleting the department also deletes all of its employees.
>>> s.commit()
>>> s.query(Employee).all()
[]
让我们创建另一个雇员来测试我们新的日期时间列“hired_on”:
>>> emp2 = Employee(name="Marry")
>>> emp2.hired_on
>>> s.add(emp2)
>>> emp2.hired_on
>>> s.commit()
>>> emp2.hired_on
datetime.datetime(2014, 3, 24, 2, 3, 46)
你注意到这个小片段有些奇怪吗?既然Employee.hired_on被定义为默认值func.now(),那么emp2.hired_on在被创建后怎么会是None ?
答案在于 SQLAlchemy 是如何处理func.now()的。func生成 SQL 函数表达式。func.now()在 SQL 中直译为 now() :
>>> print func.now()
now()
>>> from sqlalchemy import select
>>> rs = s.execute(select([func.now()]))
>>> rs.fetchone()
(datetime.datetime(2014, 3, 24, 2, 9, 12),)
正如您所看到的,通过 SQLAlchemy 数据库会话对象执行func.now()函数会根据我们机器的时区给出当前的日期时间。
在继续下一步之前,让我们删除department表和employee表中的所有记录,这样我们可以稍后从一个干净的数据库开始。
>>> for department in s.query(Department).all():
... s.delete(department)
...
>>> s.commit()
>>> s.query(Department).count()
0
>>> s.query(Employee).count()
0
更多 ORM 查询
让我们继续编写查询,以便更加熟悉 ORM API。首先,我们在两个部门“IT”和“财务”中插入几个雇员。
IT = Department(name="IT")
Financial = Department(name="Financial")
john = Employee(name="John", department=IT)
marry = Employee(name="marry", department=Financial)
s.add(IT)
s.add(Financial)
s.add(john)
s.add(marry)
s.commit()
cathy = Employee(name="Cathy", department=Financial)
s.add(cathy)
s.commit()
假设我们想找到名字以“C”开头的所有雇员,我们可以使用startswith()来实现我们的目标:
>>>s.query(Employee).filter(Employee.name.startswith("C")).one().name
u'Cathy'
让查询变得更加困难的是,假设我们想要查找姓名以“C”开头并且也在财务部门工作的所有雇员,我们可以使用一个连接查询:
>>> s.query(Employee).join(Employee.department).filter(Employee.name.startswith('C'), Department.name == 'Financial').all()[0].name
u'Cathy'
如果我们想搜索在某个日期之前雇用的员工,该怎么办?我们可以在 filter 子句中使用普通的 datetime 比较运算符。
>>> from datetime import datetime
# Find all employees who will be hired in the future
>>> s.query(Employee).filter(Employee.hired_on > func.now()).count()
0
# Find all employees who have been hired in the past
>>> s.query(Employee).filter(Employee.hired_on < func.now()).count()
3
部门和员工之间的多对多
到目前为止,一个Department可以有多个Employees,一个Employee最多属于一个Department。因此,Department和Employee之间是一对多的关系。如果一个Employee可以属于任意数量的Department呢?我们如何处理多对多的关系?
为了处理Department和Employee之间的多对多关系,我们将创建一个新的关联表“department_employee_link ”,其中外键列指向Department和Employee。我们还需要从Department中删除backref定义,因为我们将在Employee中插入一个多对多relationship。
import os
from sqlalchemy 导入列,DateTime,String,Integer,ForeignKey,func
from sqlalchemy.orm 导入关系,back ref
from sqlalchemy . ext . declarative import declarative _ base
Base = declarative _ Base()
class Department(Base):
_ _ tablename _ _ = ' Department '
id = Column(Integer,primary _ key = True)
name = Column(String)
employees = relationship(
' Employee ',
secondary = ' Department _ Employee _ link '
)
class Employee(Base):
_ _ tablename _ _ = ' Employee '
id = Column(Integer,primary _ key = True)
name = Column(String)
hired _ on = Column(
DateTime,
default = func . now())
departments = relationship(
Department,
secondary = ' Department _ Employee _ link '
)
class DepartmentEmployeeLink(Base):
_ _ tablename _ _ = ' department _ employee _ link '
department _ id = Column(Integer,ForeignKey('department.id '),primary _ key = True)
employee _ id = Column(Integer,ForeignKey('employee.id '),primary_key=True)
请注意,DepartmentEmployeeLink中的所有列“部门标识”和“员工标识”被组合在一起形成了表department_employee_link的主键,而类Department和类Employee中的relationship参数有一个指向关联表的附加关键字参数“次要”。
一旦我们定义了我们的模型,我们就可以按以下方式使用它们:
>>> fp = 'orm_in_detail.sqlite'
>>> # Remove the existing orm_in_detail.sqlite file
>>> if os.path.exists(fp):
... os.remove(fp)
...
>>> from sqlalchemy import create_engine
>>> engine = create_engine('sqlite:///orm_in_detail.sqlite')
>>>
>>> from sqlalchemy.orm import sessionmaker
>>> session = sessionmaker()
>>> session.configure(bind=engine)
>>> Base.metadata.create_all(engine)
>>>
>>> s = session()
>>> IT = Department(name="IT")
>>> Financial = Department(name="Financial")
>>> cathy = Employee(name="Cathy")
>>> marry = Employee(name="Marry")
>>> john = Employee(name="John")
>>> cathy.departments.append(Financial)
>>> Financial.employees.append(marry)
>>> john.departments.append(IT)
>>> s.add(IT)
>>> s.add(Financial)
>>> s.add(cathy)
>>> s.add(marry)
>>> s.add(john)
>>> s.commit()
>>> cathy.departments[0].name
u'Financial'
>>> marry.departments[0].name
u'Financial'
>>> john.departments[0].name
u'IT'
>>> IT.employees[0].name
u'John'
注意,我们使用Employee.departments.append()将一个Department添加到一个Employee的部门列表中。
要查找 IT 部门的员工列表,无论他们是否属于其他部门,我们可以使用relationship.any()函数。
>>> s.query(Employee).filter(Employee.departments.any(Department.name == 'IT')).all()[0].name
u'John'
另一方面,要查找 John 是其雇员之一的部门列表,我们可以使用相同的函数。
>>> s.query(Department).filter(Department.employees.any(Employee.name == 'John')).all()[0].name
u'IT'
总结和提示
在本文中,我们深入研究了 SQLAlchemy 的 ORM 库,并编写了更多的查询来探索 API。请注意,当您想要将删除从外键引用的对象级联到引用对象时,您可以在引用对象的外键定义的backref中指定cascade='all,delete'(如示例关系Employee.department中所示)。
Python 的 SQLAlchemy vs 其他 ORM
Update: A review of PonyORM has been added.
Python ORMs 概述
作为一门优秀的语言,除了 SQLAlchemy 之外,Python 还有很多 ORM 库。在本文中,我们将看看几个流行的替代 ORM 库,以更好地理解 Python ORM 的全貌。通过编写一个脚本来读写一个包含两个表person和address的简单数据库,我们将更好地理解每个 ORM 库的优缺点。
SQLObject
SQLObject 是一个 Python ORM,在 SQL 数据库和 Python 之间映射对象。由于与 Ruby on Rails 的 ActiveRecord 模式相似,它在编程社区中越来越受欢迎。SQLObject 的第一个版本发布于 2002 年 10 月。它在 LGPL 的许可下。
在 SQLObject 中,数据库概念以一种非常类似于 SQLAlchemy 的方式映射到 Python 中,其中表被映射为类,行被映射为实例,列被映射为属性。它还提供了一种基于 Python 对象的查询语言,使得 SQL 更加抽象,从而为应用程序提供了数据库不可知论。
$ pip install sqlobject
Downloading/unpacking sqlobject
Downloading SQLObject-1.5.1.tar.gz (276kB): 276kB downloaded
Running setup.py egg_info for package sqlobject
警告:未找到匹配“*”的文件。html'
警告:未找到匹配' * '的文件。css'
警告:没有找到与' docs/*匹配的文件。html'
警告:没有找到匹配' * '的文件。“tests”目录下的“py”要求已经满足(使用-升级来升级):form encode>= 1 . 1 . 1 in/Users/xiaonuogantan/python 2-workspace/lib/python 2.7/site-packages(来自 sqlobject)
安装收集的包:sqlobject
运行 setup.py install for sqlobject
将 build/scripts-2.7/SQL object-admin 的模式从 644 更改为 755
更改 build/scripts-2.7 的模式
警告:未找到匹配“*”的文件。html'
警告:未找到匹配' * '的文件。css'
警告:没有找到与' docs/*匹配的文件。html'
警告:没有找到匹配' * '的文件。“tests”目录下的“py”
将/Users/xiaonuogantan/python 2-workspace/bin/SQL object-admin 的模式更改为 755
将/Users/xiaonuogantan/python 2-workspace/bin/SQL object-convertOldURI 的模式更改为 755
成功安装 sqlobject
清理...
>>> from sqlobject import StringCol, SQLObject, ForeignKey, sqlhub, connectionForURI
>>> sqlhub.processConnection = connectionForURI('sqlite:/:memory:')
>>>
>>> class Person(SQLObject):
... name = StringCol()
...
>>> class Address(SQLObject):
... address = StringCol()
... person = ForeignKey('Person')
...
>>> Person.createTable()
[]
>>> Address.createTable()
[]
上面的代码创建了两个简单的表:person和address。要在这两个表中创建或插入记录,我们只需像普通 Python 对象一样实例化一个人和一个地址:
>>> p = Person(name='person')
>>> a = Address(address='address', person=p)
>>> p
>>>答
[/python]
为了从数据库中获取或检索新记录,我们使用附加到`Person`和`Address`类的神奇的`q`对象:
persons = Person.select(Person.q.name == ‘person’)
persons
list(persons)
[]
P1 = persons[0]
P1 = = p
True
addresses = address . select(address . q . person = = P1)
addresses
列表(地址)
[
]
a1 = addresses[0]
a1 == a
True
[/python]
暴风雨
Storm 是一个 Python ORM,在一个或多个数据库和 Python 之间映射对象。它允许开发人员跨多个数据库表构建复杂的查询,以支持对象信息的动态存储和检索。它是由 Ubuntu 背后的公司 Canonical Ltd .用 Python 开发的,用于 Launchpad 和景观应用程序,随后在 2007 年作为自由软件发布。该项目是在 LGPL 许可证下发布的,贡献者需要向 Canonical 分配版权。
像 SQLAlchemy 和 SQLObject 一样, Storm 也将表映射到类,将行映射到实例,将列映射到属性。与其他两个相比,Storm 的表类不必是特定于框架的特殊超类的子类。在 SQLAlchemy 中,每个表类都是sqlalchemy.ext.declarative.declarative_bas的子类。在 SQLObject 中,每个表类都是sqlobject.SQLObject的子类。
与 SQLAlchemy 类似,Storm 的Store对象充当后端数据库的代理,所有操作都缓存在内存中,一旦在存储上调用方法 commit,就将committed缓存到数据库中。每个存储拥有自己的映射 Python 数据库对象集,就像一个 SQLAlchemy 会话拥有不同的 Python 对象集一样。
Storm 的具体版本可以从下载页面下载。在本文中,示例代码是用 Storm 版编写的。
>>> from storm.locals import Int, Reference, Unicode, create_database, Store
>>>
>>>
>>> db = create_database('sqlite:')
>>> store = Store(db)
>>>
>>>
>>> class Person(object):
... __storm_table__ = 'person'
... id = Int(primary=True)
... name = Unicode()
...
>>>
>>> class Address(object):
... __storm_table__ = 'address'
... id = Int(primary=True)
... address = Unicode()
... person_id = Int()
... person = Reference(person_id, Person.id)
...
上面的代码创建了一个内存 sqlite 数据库和一个引用该数据库对象的存储库。Storm store 类似于 SQLAlchemy DBSession 对象,两者都管理附加到它们的实例对象的生命周期。例如,下面的代码创建一个人和一个地址,并通过刷新存储将这两个记录插入到数据库中。
>>> store.execute("CREATE TABLE person "
... "(id INTEGER PRIMARY KEY, name VARCHAR)")
> > > store.execute("创建表地址"
...”(id 整数主键,address VARCHAR,person_id 整数,“
..."外键(person_id)引用人员(id))")
> > > Person = Person()
>>>Person . name = u ' Person '
>>>打印人
> > > print "%r,%r" % (person.id,person.name)
None,u'person' #请注意,person.id 为 None,因为 person 实例尚未附加到有效的数据库存储。
>>>store . add(person)
>>>
>>>print " % r,%r" % (person.id,person.name)
None,u'person' #由于 store 还没有将 Person 实例刷新到 sqlite 数据库中,person.id 仍然是 None。
>>>store . flush()
>>>print " % r,%r" % (person.id,person.name)
1,u'person' #现在 store 已经刷新了 person 实例,我们得到了 person 的 id 值。
>>>Address = Address()
>>>address.person = person
>>>Address . Address = ' Address '
>>>print " % r,%r" % (address.id,Address . person,address.address)
None,,' Address '
>>>Address . person = = person
True
为了获取或检索插入的 Person 和 Address 对象,我们调用store.find()来找到它们:
>>> person = store.find(Person, Person.name == u'person').one()
>>> print "%r, %r" % (person.id, person.name)
1, u'person'
>>> store.find(Address, Address.person == person).one()
> > > address = store.find(Address,Address.person == person)。one()
> > > print "%r,%r" % (address.id,address.address)
1,u'address'
姜戈氏 ORM
Django 是一个免费的开源 web 应用框架,它的 ORM 被紧密地嵌入到系统中。在最初发布之后,Django 因其简单的设计和易于使用的网络特性而变得越来越受欢迎。它于 2005 年 7 月在 BSD 许可下发布。由于 Django 的 ORM 紧密地构建在 web 框架中,所以不推荐在独立的非 Django Python 应用程序中使用它的 ORM,尽管这是可能的。
Django 是最流行的 Python web 框架之一,它有自己专用的 ORM。与 SQLAlchemy 相比,Django 的 ORM 更适合直接的 SQL 对象操作,它公开了数据库表和 Python 类之间简单直接的映射。
$ django-admin.py startproject demo
$ cd demo
$ python manage.py syncdb
Creating tables ...
Creating table django_admin_log
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_groups
Creating table auth_user_user_permissions
Creating table auth_user
Creating table django_content_type
Creating table django_session
您刚刚安装了 Django 的 auth 系统,这意味着您没有定义任何超级用户。您想现在创建一个吗?(是/否):否
安装自定义 SQL...
安装索引...
从 0 个固定设备
$ python manage.py shell
安装了 0 个对象
因为我们必须先创建一个项目才能执行 Django 的代码,所以我们在之前的 shell 中创建了一个 Django 项目“demo ”,并进入 Django shell 来测试我们的 ORM 示例。
# demo/models.py
>>> from django.db import models
>>>
>>>
>>> class Person(models.Model):
... name = models.TextField()
...
... class Meta:
... app_label = 'demo'
...
>>>
>>> class Address(models.Model):
... address = models.TextField()
... person = models.ForeignKey(Person)
...
... class Meta:
... app_label = 'demo'
上面的代码声明了两个 Python 类,Person和Address,每个类都映射到一个数据库表。在执行任何数据库操作代码之前,我们需要在本地 sqlite 数据库中创建表。
python manage.py syncdb
Creating tables ...
Creating table demo_person
Creating table demo_address
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
为了将一个人和一个地址插入数据库,我们实例化相应的对象并调用这些对象的save()方法。
>>> from demo.models import Person, Address
>>> p = Person(name='person')
>>> p.save()
>>> print "%r, %r" % (p.id, p.name)
1, 'person'
>>> a = Address(person=p, address='address')
>>> a.save()
>>> print "%r, %r" % (a.id, a.address)
1, 'address'
为了获取或检索 person 和 address 对象,我们使用模型类的神奇的objects属性从数据库中获取对象。
>>> persons = Person.objects.filter(name='person')
>>> persons
[]
>>> p = persons[0]
>>> print "%r, %r" % (p.id, p.name)
1, u'person'
>>> addresses = Address.objects.filter(person=p)
>>> addresses
[
]
>>> a = addresses[0]
>>> print "%r, %r" % (a.id, a.address)
1, u'address'
[/python]
## 叫声类似“皮威”的鸟
peewee 是一个小型的、富有表现力的 ORM。与其他 ORM 相比,`peewee`专注于极简主义的原则,API 简单,库易于使用和理解。
pip install peewee
Downloading/unpacking peewee
Downloading peewee-2.1.7.tar.gz (1.1MB): 1.1MB downloaded
Running setup.py egg_info for package peewee
安装收集的包:peewee
运行 setup.py 安装 peewee
将 build/scripts-2.7/pwiz.py 的模式从 644 更改为 755
将/Users/xiaonuogantan/python 2-workspace/bin/pwiz . py 的模式更改为 755
成功安装 peewee
清理…
为了创建数据库模型映射,我们实现了映射到相应数据库表的一个`Person`类和一个`Address`类。
from peewee import SqliteDatabase, CharField, ForeignKeyField, Model
db = SqliteDatabase(‘:memory:’)
class Person(Model):
… name = CharField()
…
… class Meta:
… database = db
…
class Address(Model):
… address = CharField()
… person = ForeignKeyField(Person)
…
… class Meta:
… database = db
…
Person.create_table()
Address.create_table()
为了将对象插入数据库,我们实例化对象并调用它们的`save()`方法。从对象创建的角度来看,`peewee`和 Django 很像。
p = Person(name=‘person’)
p.save()
a = Address(address=‘address’, person=p)
a.save()
为了从数据库中获取或检索对象,我们从它们各自的类中`select`对象。
person = Person.select().where(Person.name == ‘person’).get()
person
print ‘%r, %r’ % (person.id, person.name)
1, u’person’
address = Address.select().where(Address.person == person).get()
print ‘%r, %r’ % (address.id, address.address)
1, u’address’
## 波尼奥姆
[PonyORM](https://ponyorm.org/) 允许您使用 Python 生成器查询数据库。这些生成器被翻译成 SQL,结果被自动映射成 Python 对象。将查询编写为 Python 生成器使得程序员可以很容易地快速构造某些查询。
例如,让我们使用 PonyORM 查询 SQLite 数据库中以前的`Person`和`Address`模型。
from pony.orm import Database, Required, Set
db = Database(‘sqlite’, ‘:memory:’)
class Person(db.Entity):
… name = Required(unicode)
… addresses = Set(“Address”)
…
class Address(db.Entity):
… address = Required(unicode)
… person = Required(Person)
…
db.generate_mapping(create_tables=True)
现在我们在内存中有了一个 SQLite 数据库,两个表映射到了`db`对象,我们可以将两个对象插入到数据库中。
p = Person(name=“person”)
a = Address(address=“address”, person=p)
db.commit()
调用`db.commit()`实际上将新对象`p`和`a`提交到数据库中。现在我们可以使用生成器语法查询数据库。
from pony.orm import select
select(p for p in Person if p.name == “person”)[:]
[Person[1]]
select(p for p in Person if p.name == “person”)[:][0].name
u’person’
select(a for a in Address if a.person == p)[:]
[Address[1]]
select(a for a in Address if a.person == p)[:][0].address
u’address’
## sqllcemy(SQL 语法)
[SQLAlchemy](http://www.sqlalchemy.org/ "SQLAlchemy") 是在 MIT 许可下发布的 Python 编程语言的开源 SQL 工具包和 ORM。它最初于 2006 年 2 月发布,作者是迈克尔·拜尔。它提供了“一整套众所周知的企业级持久化模式,设计用于高效和高性能的数据库访问,适应于简单和 Pythonic 化的领域语言”。它采用了数据映射模式(像 Java 中的 Hibernate)而不是活动记录模式(像 Ruby on Rails 中的模式)。
SQLAlchemy 的工作单元原则使得有必要将所有数据库操作代码限制在特定的数据库会话中,该会话控制该会话中每个对象的生命周期。与其他 ORM 类似,我们从定义`declarative_base()`的子类开始,以便将表映射到 Python 类。
from sqlalchemy import Column, String, Integer, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Person(Base):
… tablename = ‘person’
… id = Column(Integer, primary_key=True)
… name = Column(String)
…
class Address(Base):
… tablename = ‘address’
… id = Column(Integer, primary_key=True)
… address = Column(String)
… person_id = Column(Integer, ForeignKey(Person.id))
… person = relationship(Person)
…
在我们编写任何数据库代码之前,我们需要为我们的数据库会话创建一个数据库引擎。
from sqlalchemy import create_engine
engine = create_engine(‘sqlite:///’)
一旦我们创建了一个数据库引擎,我们就可以继续创建一个数据库会话,并为之前定义为`Person`和`Address`的所有数据库类创建表。
from sqlalchemy.orm import sessionmaker
session = sessionmaker()
session.configure(bind=engine)
Base.metadata.create_all(engine)
现在,`session`对象变成了我们的工作单元构造器,所有后续的数据库操作代码和对象都将被附加到一个通过调用它的`__init__()`方法构建的 db 会话上。
s = session()
p = Person(name=‘person’)
s.add§
a = Address(address=‘address’, person=p)
s.add(a)
为了获取或检索数据库对象,我们从 db session 对象中调用`query()`和`filter()`方法。
p = s.query(Person).filter(Person.name == ‘person’).one()
p
print “%r,%r” % (p.id,p.name)
1、’ person ’
a = s . query(地址)。filter(Address.person == p)。一()
打印“%r,% r”%(a . id,a.address)
1、‘地址’
请注意,到目前为止,我们还没有提交对数据库的任何更改,因此新的 person 和 address 对象实际上还没有存储在数据库中。调用`s.commit()`将实际提交更改,即向数据库中插入一个新的人和一个新的地址。
s.commit()
s.close()
## Python ORMs 之间的比较
对于本文中介绍的每个 Python ORM,我们将在这里列出它们的优缺点:
### SQLObject
**优点:**
1. 采用了易于理解的 ActiveRecord 模式
2. 相对较小的代码库
**缺点:**
1. 方法和类的命名遵循 Java 的 camelCase 风格
2. 不支持数据库会话来隔离工作单元
### 暴风雨
**优点:**
1. 一个简洁、轻量级的 API,可以缩短学习曲线,实现长期可维护性
2. 不需要特殊的类构造函数,也不需要命令式基类
**缺点:**
1. 迫使程序员编写手动创建表的 DDL 语句,而不是从模型类中自动派生出来
2. Storm 的贡献者必须将他们贡献的版权给 Canonical 有限公司。
### 姜戈氏 ORM
**优点:**
1. 易于使用,学习曲线短
2. 与 Django 紧密集成,使其成为处理 Django 数据库时的 de-factor 标准
**缺点:**
1. 不能很好地处理复杂的查询;迫使开发人员回到原始 SQL
2. 与 Django 紧密结合;这使得它很难在 Django 上下文之外使用
### 叫声类似“皮威”的鸟
**优点:**
1. 一个 Django-ish API;使其易于使用
2. 轻量级实现;使其易于与任何 web 框架集成
**缺点:**
1. 不支持自动模式迁移
2. 编写多对多查询并不直观
### sqllcemy(SQL 语法)
**优点:**
1. 企业级 APIs 使代码健壮且适应性强
2. 灵活的设计;使得编写复杂的查询变得轻松
**缺点:**
1. 工作单元的概念并不常见
2. 一个重量级的 API 导致漫长的学习曲线
### 波尼奥姆
**优点:**
1. 用于编写查询的非常方便的语法
2. 自动查询优化
3. 简化的设置和使用
**缺点:**
1. 不是为同时处理数十万或数百万条记录而设计的
## 总结和提示
与其他 ORM 相比,SQLAlchemy 突出了它对工作单元概念的关注,这在您编写 SQLAlchemy 代码时非常普遍。最初,DBSession 的概念可能很难理解和正确使用,但稍后您会体会到额外的复杂性,它将与数据库提交时间相关的意外错误减少到几乎为零。在 SQLAlchemy 中处理多个数据库可能很棘手,因为每个数据库会话都被限制在一个数据库连接中。然而,这种限制实际上是一件好事,因为它迫使您认真考虑多个数据库之间的交互,并使调试数据库交互代码变得更容易。
在以后的文章中,我们将全面探索 SQLAlchemy 更高级的用例,以真正掌握其强大的 API。
堆栈教程:实现初学者指南
原文:https://www.pythoncentral.io/stack-tutorial-python-implementation/
先决条件
为了理解这个堆栈教程,你需要学习堆栈数据结构,这需要:
- Python 3
- 基本数据结构概念如列表(点击 此处 刷新列表概念)
- OOP 概念
什么是栈?
你好!如果你正在阅读这篇文章,你将会学到一个非常基本和最有用的数据结构概念。如果你懂其他语言,比如 C 或 C++,stack 的实现可能会很棘手(因为你必须跟踪指针!)但不是用 Python。Python 是如此神奇,以至于你可以使用列表来轻松地实现它们,但是你也将学习如何使用指针来采用一种语言不可知的方式来实现它们。但首先,让我们了解它们是什么。如果您已经熟悉了这一点,可以跳到实现部分。
当你听到书库这个词时,你首先想到的可能是一摞书,我们可以用这个类比来轻松解释书库!一些共性包括:
- 在书库的顶部有一本书(如果书库中只有一本书,那么这本书将被认为是最上面的书)。
- 只有拿走最上面的书,你才能拿到最下面的书。这里没有叠衣服游戏!(同时假设你一次只能举起一本书)。
- 一旦你一本书一本书地从上面拿走,就没有书剩下了,因此你不能再拿走更多的书。
看看这款名为 河内之塔 的有趣游戏,它完美地展示了堆栈是如何工作的。仔细阅读说明,关掉音乐(声音太大了!).

用编程的方式描述以上几点:
- 跟踪最顶端的元素,因为这将为您提供关于堆栈中元素数量以及堆栈是否为空/满的信息(如果堆栈为空,则 top 将被设置为 0 或负数)
- 最后进入堆栈的元素总是第一个离开(后进先出)
- 如果所有的元素都被移除,那么堆栈是空的,如果你试图从一个空的堆栈中移除元素,会抛出一个警告或错误信息。
- 如果堆栈已经达到最大限制,而你试图添加更多的元素,就会抛出一个警告或错误信息。
要记住的事情:
- 元素的进入和退出只发生在堆栈的一端(顶部)
- 将一个元素推入堆栈
- 从堆栈中取出一个元素
- 不允许随机访问——不能从中间添加或删除元素。
注意:始终跟踪顶部。这告诉我们堆栈的状态。
如何实现堆栈?
现在你知道什么是栈了,让我们开始实现吧!
栈实现使用列表
这里我们将定义一个类堆栈并添加方法来执行下面的操作:
- 将元素推入堆栈
- 从堆栈中弹出元素,如果为空则发出警告
- 获取堆栈的大小
- 打印堆栈的所有元素
class Stack:
#Constructor creates a list
def __init__(self):
self.stack = list()
#Adding elements to stack
def push(self,data):
#Checking to avoid duplicate entries
if data not in self.stack:
self.stack.append(data)
return True
return False
#Removing last element from the stack
def pop(self):
if len(self.stack)<=0:
return ("Stack Empty!")
return self.stack.pop()
#Getting the size of the stack
def size(self):
return len(self.stack)
myStack = Stack()
print(myStack.push(5)) #prints True
print(myStack.push(6)) #prints True
print(myStack.push(9)) #prints True
print(myStack.push(5)) #prints False since 5 is there
print(myStack.push(3)) #prints True
print(myStack.size()) #prints 4
print(myStack.pop()) #prints 3
print(myStack.pop()) #prints 9
print(myStack.pop()) #prints 6
print(myStack.pop()) #prints 5
print(myStack.size()) #prints 0
print(myStack.pop()) #prints Stack Empty!
**注意:**我们不担心堆栈的大小,因为它是由一个可以动态改变大小的列表来表示的。
使用数组的堆栈实现
Python 列表使得实现堆栈变得如此容易。然而,如果你想不可思议地实现堆栈语言,你必须假设列表就像数组(大小固定),并使用一个顶部指针来记录堆栈的状态。查看 这个 动画来了解它的工作原理。
算法
- 声明一个链表和一个整数 MaxSize,表示栈的最大大小
- Top 初始设置为 0
- 推送操作:
- 检查 Top 是否小于堆栈的 MaxSize
- 如果是,将数据追加到堆栈,并将 top 加 1
- 如果否,打印堆栈满信息
- 检查 Top 是否小于堆栈的 MaxSize
- 弹出操作:
- 检查 Top 是否大于 0:
- 如果是,从列表中弹出最后一个元素,并将 top 减 1
- 如果否,打印堆栈空消息
- 检查 Top 是否大于 0:
- 尺寸操作:
- 顶部指针的值是堆栈的大小
程序
class Stack:
#Constructor
def __init__(self):
self.stack = list()
self.maxSize = 8
self.top = 0
#Adds element to the Stack
def push(self,data):
if self.top>=self.maxSize:
return ("Stack Full!")
self.stack.append(data)
self.top += 1
return True
#Removes element from the stack
def pop(self):
if self.top<=0:
return ("Stack Empty!")
item = self.stack.pop()
self.top -= 1
return item
#Size of the stack
def size(self):
return self.top
s = Stack()
print(s.push(1))#prints True
print(s.push(2))#prints True
print(s.push(3))#prints True
print(s.push(4))#prints True
print(s.push(5))#prints True
print(s.push(6))#prints True
print(s.push(7))#prints True
print(s.push(8))#prints True
print(s.push(9))#prints Stack Full!
print(s.size())#prints 8
print(s.pop())#prints 8
print(s.pop())#prints 7
print(s.pop())#prints 6
print(s.pop())#prints 5
print(s.pop())#prints 4
print(s.pop())#prints 3
print(s.pop())#prints 2
print(s.pop())#prints 1
print(s.pop())#prints Stack Empty!
**注:**未添加元素 9,因此大小仍为 8。
除了上面描述的方法之外,您还可以添加方法来返回顶部元素,检查堆栈是否为空等等。
结论
堆栈的一个主要应用是在递归中。请务必查看这篇教程,了解什么是递归。一旦你熟悉了这个概念,试着用递归- 句子颠倒和平衡括号来解决这些难题。快乐的蟒蛇!
如何开始 Python 开发人员的职业生涯
原文:https://www.pythoncentral.io/starting-a-career-as-a-python-developer/
没有多少人知道成为专业开发人员的途径。然而,软件工程师和程序员在世界范围内需求量很大,不再是新闻。因此,作为一名开发人员工作无疑会有不错的报酬。你不需要成为 python 编程的专家,就可以开始开发人员的职业生涯;只要对这门语言有一个基本的了解,就能帮助你在这个领域找到初级 python 远程工作。你会在工作中提高自己的技能。
Python 是世界上最常用的编程语言之一。也是新手最容易快速学会的一种。Python 开发者利用 python 编程语言来设计、编码和执行项目。
Python 的调试、实现、开发都是由 python 开发者来完成的。
专业人士,如程序员、数据科学家、在线和移动应用程序开发人员、软件工程师等。,利用这种语言来创建所需的任务。创建的项目和应用程序是专门为满足开发者雇主的需求而设计的。一些 python 程序员甚至可能执行独立的工作来解决一些人的问题。
在这方面,我们与来自 job aggregator Jooble 的专业 python 开发人员合作,讨论作为 python 开发人员开始职业生涯的程序。让我们深入研究一下细节。
- 学会使用 Python
成为 python 开发者的第一步是学习使用 python 编码。有很多方法可以选择学习 python;你可以参加在线 python 课程,参加 python 编码训练营,甚至可以通过观看 YouTube 上的视频自学。
Python 使用广泛,对于没有编码背景的人来说相对容易。它是一种被广泛推荐给每个开发人员了解的语言,因为它在编码的几个方面都很有帮助。
- 提高你的技能
学会 python 编程后,有必要通过参与不同的项目来提高你的技能和能力,这将帮助你成为一名优秀的开发人员。这不仅有助于提高你对 python 的熟练程度和熟悉程度,还能给你提供将来急需的经验。
你可以通过建立网站、开发游戏应用等工作来磨练自己的技能。另一种方式是做自由职业者;这样做,你会提高自己的技能,会赚钱,会有信誉。
还有,几乎每个开发者都使用 GitHub 。在 GitHub 上,你可以搜索其他人的库,并为他们链接的项目做贡献。通过为已经完成的工作增加价值,这种技术证明了您具备成为 python 开发人员的素质。
- 推销自己
在你成功地学会了如何使用 python 编码之后,你必须推销自己,展示你的技能。你需要一份写得很好的简历,突出你的证书和技能。你还应该创建一个项目和任务组合,展示你为雇主做了什么。
结论
根据几份报告,由于对 python 程序员需求的增加,许多人对从事 python 开发感兴趣。专业开发人员也发现 python 有许多特性,使它在其他编程语言中脱颖而出。
尽管成为一名专业的 python 开发人员不需要任何特定的经验或背景,但是有几种方法可以让你开始职业生涯。然而,要想成功,你需要彻底理解 python。
在 Python 中交换值
在 Python 中交换两个变量的值实际上是一个非常简单的任务。Python 使得交换两个值变得相当容易,而不需要大量笨重的代码或奇怪的代码。使用下面的内置方法,看看交换两个数字有多容易:
x, y = 33, 81
print(x, y)
x, y = y, x
print(y, x)
第一个示例的结果是 33,81,而第二个示例的结果将被交换,因此结果为 81,33。这种交换可以用任何类型的变量来实现,不仅限于数字,也可以用于字符串。
Python 开发的文本编辑器与 ide:选择正确的工具
原文:https://www.pythoncentral.io/text-editors-vs-ides-for-python-development-selecting-the-right-tool/
你用来编程的语言和它的解释器或编译器只是你用来开发软件的一些工具。另一个重要的事情是你的编程环境。不像有些语言,你的选择是有限的,如 Delphi 或。NET 语言,有一两个明显更好的选择,Python 没有“标准”工具;Python 开发人员可以使用各种各样的编辑器和 ide。为自己选择合适的工具并不困难,但也不能掉以轻心:通过深入了解这些工具的特性,您可以充分利用它们,因此最好预先做出正确的选择,以避免浪费精力。
编辑器还是 IDE?
无论是面对面还是在讨论网站上,当有人问什么样的 IDE 最适合 Python 时,会有两种回答:一种是建议您最喜欢的 Python IDE,另一种是指出 IDE 对 Python 编程(或者在更极端的情况下,一般的编程)几乎没有什么帮助。我承认我的先入之见:我属于后一种阵营。我用 Emacs 处理几乎所有可以用文本表示的东西,我发现它非常高效和灵活。然而,我会试着抛开我的偏见,公正地讨论这件事。
语言方面的联系
在有些语言中,你会发现开发人员普遍认为 IDE 是必需的:Java、Delphi、C#和 VB.NET 就是明显的例子。所有这些语言都有一个共同的特点,那就是有大量的原始代码,这些代码对编译器来说是必需的,但对你的应用程序来说在语义上没有意义,而且必须是现成的;在 Java 和 C#中,你必须在调用函数之前定义一个类,而在 Delphi 中,你必须在一个地方定义一个函数的接口,在其他地方实现逻辑。ide 在这方面很棒;他们为你生成所有的样板代码。
Python(像 Perl、Go、Ruby 和 Lisp 等等)是不同的。样板文件较少;几乎你输入的每个字符都直接表达了你想要创建的功能。你可以说,低挂的 IDE 水果更少了。这使得 IDE 的使用成为一个更有争议的话题,Python 程序员在这个问题上的分歧也支持这个观点。
ide 会让程序员变得更糟吗?
IDE 的明显优势是它为您做了很多工作。当然,许多文本编辑器也可以配置成这样,但是 IDE 可以省去您这个麻烦。理想情况下,使用 IDE 比使用简单(或不太简单)的文本编辑器更有效率。那么为什么会有人继续抵制 IDEs 呢?
许多开发人员提出的支持文本编辑器的一个问题是,对 ide 的过度依赖阻碍了他们的用户深入学习他们的语言。这是有一定道理的。如果你依赖自动补全来提醒你函数、类和方法的名字,那就有你永远也学不会它们的危险;对于许多相当快的打字员来说,包括我自己,输入你知道的名字比使用自动补全要快。代码片段也是如此:如果你总是使用代码片段插入类定义,你可能永远也不会自己学会语法。
当然,如果你一直有你的 IDE,那也不一定是问题,不是吗?嗯,也许吧。从某种意义上来说,IDE 提供的功能越多,在某种程度上,对的约束就越多,因为一旦 IDE 为您解决了编码问题,它就会倾向于将您的解决方案限制在 IDE 提供的范围内。在某种程度上,这是真的,您的 IDE 可能会导致您选择不太理想的开发路径,仅仅是因为它工作得太好了。
适合您的工具
也就是说,许多 Python 程序员使用 ide,许多人不使用,他们都很有效率,并且对自己的选择很满意。在我看来,如果你对你最喜欢的文本编辑器感到满意,你可能会更好地使用它。如果你已经是一个 IDE 的人,你知道你想要什么;看看 IDEs。但如果你是骑墙派,你该如何选择?我认为一个很好的指标是你现在如何使用程序。你打字很快吗?你是一个键盘快捷键迷吗?你每次触摸鼠标都把它视为一次失败吗?如果您使用文本编辑器,尤其是像 Emacs 或 Sublime Text 这样高度可定制的编辑器,您可能会更高兴。如果另一方面。你是一个鼠标爱好者,你可能更喜欢 IDE。
另一个需要考虑的要点是你对编程语言的使用;如果您希望 Python 成为您的主要语言,很少使用其他语言,或者您希望使用 Python 作为您唯一的非 IDE 绑定语言,IDE 可能是一个好主意;您将会很好地使用它,它将会成为 Python 的一个有效工具。另一方面,如果你(像我一样)是一个语言爱好者,喜欢像左宗棠鸡这样的语言,你可能会想要使用文本编辑器;你可以用一个编辑器变得非常流利,你用它开发的技能将使你在所有语言中更有效率,尽管你可能没有使用任何特定语言的最方便的工具。
最后,如果你刚刚开始学习 Python,让我为简单的编辑器插上一个插头:你最好学习这种语言和它的库自己写,然后然后如果你认为 IDE 会加快你的工作,使用它。如果你走这条路,你会发现你学语言更快更彻底。
注意:我已经将我们的选择限制在跨平台编辑器和 ide 上,因为 Python 是一种跨平台语言,无论您多么喜欢您当前的操作系统,您都可能会发现自己在某个时候使用不同的操作系统,并且您会希望拥有自己熟悉的工具。此外,有这么多好的跨平台选项,将自己局限于单平台工具是愚蠢的。列出的所有选项都可以在 Windows、Linux 和 Mac OS X 上运行,有些还可以在数量惊人的其他平台上运行。
另外,我是从一个初级 Python 程序员的角度来考虑这个话题的。考虑到这一点,我在定制方面做得很少,除了高度可定制的编辑器,如 Emacs、Vim 和 Sublime Text。ide 尤其如此;我的立场是,如果一个工具应该是 Python 专用的,并且做所有的事情,那么它应该是开箱即用的,所以我主要在基本安装指令创建的状态下测试 ide。如果这对你来说不公平,请记住这是偏见的来源。
我们将从编辑开始。
基础知识:连接字符串
原文:https://www.pythoncentral.io/the-basics-concatenating-strings/
串联字符串基本上意味着将许多字符串加在一起形成一个更长的字符串。在 Python 中使用“+”符号可以很容易地做到这一点。
假设你有三根弦:
"I am", "Learning", "Python"
要连接它们,只需使用“+”符号将它们加在一起,就像这样:
>>> print "I am" + "Learning" + "Python"
你的输出应该是:“我在学 Python”。
您还可以在变量中连接字符串,如下所示:
string1 = "I am"
string2 = "Learning"
string3 = "Python"
>>> print string1 + string 3
在这种情况下,您的输出将是“我是 Python”。
基础知识:何时使用 del 语句
原文:https://www.pythoncentral.io/the-basics-when-to-use-the-del-statement/
使用 del 语句相对简单:它用于删除一些东西。它通常用于通过引用项目的索引而不是其值来从列表中删除项目。例如,如果您有以下列表:
list = [4, 8, 2, 3, 9, 7]
并且您想要删除索引为 4 的数字 9,因为它是列表中的第 5 个项目(索引从 0 开始),您可以使用 del 语句来执行此操作,如下所示:
del list[4]
因此,您的列表现在将如下所示:
list = [4, 8, 2, 9, 7]
可以用于开发的最好的 Python IDEs
原文:https://www.pythoncentral.io/the-best-python-ides-you-can-use-for-development/
This article was written by Sergio Tapia Gutierrez. If you’re after another opinion by Jason Fruit, checkout our other IDE article Comparison of Python IDEs for Development. We also have a Review of Python’s Best Text Editors.
IDE ( 集成开发环境)是程序员可以使用的最好的工具之一。它允许开发人员高效地工作,忘记样板文件。
虽然一些程序员对使用文本编辑器以外的任何东西的想法嗤之以鼻,但是当您正在处理一个包含许多文件的非常大的项目时,IDE 将具有使您作为开发人员的生活更加容易的特性。
一个好的 IDE 应该具备的一些特性是:
- 代码完成
- 语法突出显示
- 通用代码模板
- 源代码控制支持(例如 Subversion、Mercurial 或 Git
让我们看看哪些 Python IDE 是最好的,以及它们是如何相互比较的。

PyDev 的 Eclipse
PyDev 的 Eclipse

PyDev 的 Eclipse
PyDev 官方网站:http://pydev.org/
Eclipse 是一个非常通用的 IDE,已经存在很长时间了。这是经过时间考验的产品,非常可靠。Eclipse 就像一个沙盒 IDE 它可以支持任何语言,只要有人通过一个包来支持它。PyDev 就是这种情况,这个包允许您将 Eclipse 变成一个非常有用的 Python IDE。
这是一个完全免费 IDE,提供了大量的功能,例如:
- Django 一体化
- 代码完成
- 自动导入的代码完成
- 语法突出显示
- 代码分析
- 转到定义
- 重构
- 标记事件
- 调试器
- 远程调试器
- 令牌浏览器
- 交互式浏览器
- 单元测试集成
- 代码覆盖率
- 还有很多很多
我在我的 Windows 机器上用 Python 编码时使用了这个,它只需很少的配置就能工作。
Komodo Edit

Komodo Edit -可在 Windows、Linux 和 Mac 上使用。
科莫多编辑官网:http://www.activestate.com/komodo-edit
Komodo Edit 是一个非常干净、专业的 Python IDE。它没有绒毛,而是专注于把你需要的东西放在你面前。没有挖掘随机子菜单寻找一个选项。它的代码完成非常好,速度很快;它会在你输入的时候弹出,只需要很少的加载时间。
ActiveState 提供了他们 IDE 的商业版本,名为 Komodo IDE 。
两个版本之间的差异如下:

Komodo Edit vs. Komodo IDE
皮查姆

JetBrains 的 PyCharm
PyCharm 官方网站:http://www.jetbrains.com/pycharm/
PyCharm 是由 JetBrains 创建的 IDE。你可能记得这些人是 T2 ReSharper T3 的作者,这是. NET 开发者可以做的最好的投资之一。PyCharm 也不例外,JetBrains 延续了其优秀的血统,向开发者生态系统发布了另一个优秀的工具。
据说拥有绝对最好的代码完成技术,这至少值得您尝试一下。
- 跨平台
- 商业
- 自动代码完成
- 集成 Python 调试
- 错误标记
- 源代码管理集成
- 智能缩进
- 括号匹配
- 加行号
- 代码折叠
- 单元测试
节省时间的最佳 Python 库
原文:https://www.pythoncentral.io/the-best-python-libraries-to-save-time/
机器学习和软件开发是所有用 Python 创建的开源项目的很大一部分。近年来,这些项目在开源开发领域创造了许多就业机会。用 Python 编写的最流行的开源项目有 TensorFlow、Keras、Scikit-learn、Flask、Django、Tornado、Pandas、Kivy、Matplotlib 和 Requests。**1 . tensor flow .**tensor flow 是一个开源软件库,用于各种任务的机器学习。该库由谷歌开发,以满足系统的需求,这些系统可以创建和训练神经网络,以检测和解码图像和相关性,类似于人类使用的教导和表示。
- Keras
Keras 是用 Python 编写的开源神经网络库,能够在深度学习、TensorFlow、Theano 等软件上运行。它最初是为了用深度神经网络进行实验而创建的。Keras 的重点是模块化、可用性和可扩展性。
- Scikit-learn.
Scikit-learn 是一个库,它通过 Python 编程语言的一个接口为监督和非监督学习提供了各种算法。这个库是在“简化的 BSD 许可证”下发布的,并且发布了许多不同版本的 Linux,从而促进了 Scikit-learn 的商业和学术使用。
数据可视化的最佳 Python 库
数据是任何 研究论文写作的主要部分之一 ,但是很难高效地处理大量的数据。数据可视化使您能够更轻松地可视化信息。例如,通过创建一种信息地图。今天我们将看看可以在 Python 项目中使用的五个最好的数据可视化库。
- matplotlib
Matplotlib 是最流行的数据可视化 Python 库。可用于 Python 和 IPython shells、Python 脚本、web 应用服务器等。这是一个超过 10 年历史的 2D 图形图书馆,带有一个互动平台。 你可以将这个库用于各种用途,比如创建图表、直方图、功率谱、词干列表图、饼状图。Matplotlib 最大的优点是,您只需编写几行代码,其余的由它自己处理。 Metaplotilib 使用 Qt 和 GTK 等工具包,专注于静态图像和交互式图形的发布。
- Seaborn
Seaborn 数据可视化库也是基于 Matplotlib。如果您正在为您的工作寻找更高级的选项,请尝试这个 Python 库。 它带有一个功能齐全的界面,用于绘制有吸引力的、信息丰富的统计图形。它基于 KDE 的可视化 API 比其他类似的库更简洁。Seaborn 努力使可视化成为理解和探索数据的核心部分。Seaborn 与 PyData 栈完全集成,包括对 NumPy 和 pandas 数据结构的支持。
- 牛郎星。
这是一个基于流行的 Vega-Lite 可视化语法的声明性统计库。Altair 是一致的,有一个简单的 API。 使用这个数据可视化库,你可以用最少的代码创建美观高效的可视化效果。毕竟,在声明式库中,您只需要提到数据列与编码通道之间的一个链接,其余的将被自动处理。
- 阴谋地
Plotly 是一个基于网络的数据可视化工具包,它具有独特的功能,如树状图、3D 图和等高线图,这在其他库中并不常见。它有一个很棒的 API,提供了点状图、线状图、直方图、误差直方图、盒状图和其他可视化。
- ggplot
ggplot 是一个声明式图形创建系统。它基于 R 编程语言的图形语法,并与 Pandas 紧密集成。ggplot 只需要您声明如何映射要使用的变量,其余的自动处理。 如果你知道任何其他的图书馆应该在这个列表中占有一席之地,请在下面的评论中告诉我们。
Visual Studio 代码的最佳 Python 教程(一本写得很好的指南)
原文:https://www.pythoncentral.io/the-best-python-tutorial-for-visual-studio-code-a-well-written-guide/
开始您的 Python 之旅可能会非常激动人心,尤其是如果您以前从未安装过 IDE 的话。这个过程非常简单,不需要太多时间就可以完成。
在本指南中,我们将引导您安装 Visual Studio 代码和 Python 开发所需的扩展。我们还概述了如何输入代码、保存文件和运行程序。
为 Python 安装和配置 Visual Studio 代码
你可能听说过微软的 Visual Studio,但是除了名字之外,VS Code 与这个工具没有任何共同之处。由于它内置的对扩展的支持,你可以用 VS 代码编写多种语言的程序。
Windows、Mac、Linux 上都有 VS 代码,IDE 每月更新。
要在您的操作系统上安装该程序,请访问 官方网站 ,将鼠标悬停在下载按钮上的箭头上即可找到该工具的稳定版本。
在 Windows 上,运行安装程序并遵循安装说明将完成安装。在 Mac 上,您需要将下载的“Visual Studio Code.app”文件拖到 applications 文件夹中。
要在 Ubuntu 或 Debian 机器上安装 VS 代码,可以在终端中运行以下命令:
sudo apt 安装。/ <文件>。deb
VS 代码 Python 扩展
为了使 VS 代码能够与您选择的编程语言一起工作,您需要安装相关的扩展。安装 Python 扩展可以解锁 VS 代码中的以下特性:
- 自动 conda 使用和虚拟环境
- 使用智能感知完成代码
- Jupyter 环境和 Jupyter 笔记本中的代码编辑
- 代码片段
- 调试支持
- 林挺
- 支持 Python 3.4 及更高版本,以及 Python 2.7
- 单元测试支持
要安装扩展,按 Ctrl+Shift+X 打开扩展视图。您也可以通过单击活动栏上的扩展图标来完成此操作。
搜索“Python ”,点击安装按钮,从 VS 代码市场安装这个扩展。你也可以在这里 找到市集上的分机 。
用 VS 代码编写并运行 Python 程序
单击顶部栏上的文件,然后单击新建,打开一个新文件。您可以使用的快捷键是 Ctrl+n。
现在,您可以开始在新文件中输入代码。但是需要注意的是,VS 代码不会识别你写代码的语言。这是因为它不知道文件类型是什么。
您可以通过保存文件来激活 Python 扩展。“文件”菜单中提供了“保存”选项,但是您可以使用 Ctrl+S。py 扩展名附加在文件上,VS 代码会识别你的代码。
输入代码后,您可以在代码编辑器窗口内单击鼠标右键,然后单击“在终端中运行 Python 文件”来运行代码终端将出现在屏幕底部,显示程序的输出。
快速提示:Python 中列表和数组的区别
原文:https://www.pythoncentral.io/the-difference-between-a-list-and-an-array/
Python 中使用数组和列表来存储数据,但它们的用途并不完全相同。它们都可以用来存储任何数据类型(实数、字符串等),并且都可以被索引和迭代,但是两者之间的相似之处就不多了。列表和数组的主要区别在于可以对它们执行的功能。例如,您可以将一个数组除以 3,数组中的每个数字将被除以 3,如果您请求的话,结果将被打印出来。如果你试图将一个列表除以 3,Python 会告诉你做不到,并抛出错误。
它是这样工作的:
x = array([3, 6, 9, 12])
x/3.0
print(x)
在上面的示例中,您的输出将是:
array([1, 2, 3, 4])
如果您尝试对列表做同样的事情,结果会非常相似:
y = [3, 6, 9, 12]
y/3.0
print(y)
这几乎和第一个例子完全一样,除了你不会得到一个有效的输出,因为代码会抛出一个错误。
使用数组确实需要一个额外的步骤,因为它们必须被声明,而列表不需要,因为它们是 Python 语法的一部分,所以列表通常在两者之间使用得更多,这在大多数时候都很好。然而,如果你要对你的列表执行算术函数,你真的应该使用数组。此外,数组将更紧凑、更高效地存储数据,因此,如果您存储大量数据,也可以考虑使用数组。
str 和 repr 的区别
原文:https://www.pythoncentral.io/the-difference-between-str-and-repr/
str 和 repr 在 Python 中的用法非常相似,但它们不可互换。str 是一个内置函数,用于计算对象的非正式字符串表示形式,而 repr 必须用于计算对象的正式字符串表示形式。非正式和正式表述之间的明显差异与引号有很大关系。看看下面的例子:
【python】
x = 6
repr(x)
‘6’
str(x)
‘6’
y= ‘一个字符串’
repr(y)
y= ‘一个字符串’ "
str(y)
y= ‘一个字符串’
[/python]
你可以在上面的例子中看到第一个例子(x)的输出是相同的,但是当你使用 repr 和 str 字符串而不是数字时,会有明显的区别。使用 repr 返回单引号和双引号内的输出,而 str 返回的输出与字符串声明时完全相同(在单引号内)。引号(以及 repr 和 str)很重要,因为非正式表示不能作为 eval 的参数调用,否则返回值就不是有效的 string 对象。如果需要调用输出作为 eval 的参数,请确保使用 repr 而不是 str。
Python 正则表达式的零星内容
原文:https://www.pythoncentral.io/the-odds-ends-of-python-regular-expressions/
在本系列的前两部分中,我们研究了正则表达式的一些相当高级的用法。在这一部分中,我们后退一步,看看 Python 在 re 模块中提供的一些其他函数,然后我们讨论一些人们经常犯的错误(哈!)制造。
有用的 Python 正则表达式函数
Python 提供了几个函数,使得使用正则表达式操作字符串变得很容易。
- 通过一条语句,Python 可以返回与正则表达式匹配的所有子字符串的列表。
例如:
>>> s = 'Hello world, this is a test!'
>>> print(re.findall(r'\S+', s))
['Hello', 'world,', 'this', 'is', 'a', 'test!']
\S表示任何非空白字符,所以正则表达式\S+表示匹配一个或多个非空白字符(例如一个单词)。
- 我们可以用另一个字符串替换每个匹配的子字符串。
例如:
>>> print(re.sub( r'\S+' , 'WORD', s))
WORD WORD WORD WORD WORD WORD
对re.sub的调用用字符串“WORD”替换正则表达式(如单词)的所有匹配。
- 或者,如果您想遍历每个匹配的子字符串并自己处理它,
re.finditer将遍历每个匹配,并在每次遍历时返回一个MatchObject。
例如:
>>> for mo in re.finditer(r'\S+', s):
... print('[%d:%d] = %s' % (mo.start(), mo.end(), mo.group()))
[0:5] = Hello
[6:12] = world,
[13:17] = this
[18:20] = is
[21:22] = a
[23:28] = test!
- Python 也有一个函数,使用正则表达式作为分隔符,将字符串分割成多个部分。假设我们有一个字符串,它使用逗号和分号作为分隔符,到处都是空格。
例如:
s = 'word1,word2 , word3;word4 ; word'
分隔符的正则表达式是:\s*[,;]\s*。
或者用简单的英语说:
- 零个或多个空白字符。
- 逗号或分号。
- 零个或多个空白字符。
这就是它的作用:
>>> s = 'word1,word2 , word3;word4 ; word5'
>>> print(re.split(r'\s*[,;]\s*', s))
['word1', 'word2', 'word3', 'word4', 'word5']
每个单词都已被正确拆分,并删除了空格。
常见的 Python 正则表达式错误
搜索多行字符串时不使用 DOTALL 标志
在正则表达式中,特殊字符.表示匹配任何字符。
例如:
>>> s = 'BEGIN hello world END'
>>> mo = re.search('BEGIN (.*) END', s)
>>> print(mo.group(1))
hello world
但是,如果被搜索的字符串由多行组成,**。**不匹配换行符(\n)。
>>> s = '''BEGIN hello
... world END'''
>>> mo = re.search('BEGIN (.*) END', s)
>>> print(mo)
None
我们的正则表达式说找到单词 BEGIN,然后是一个或多个字符,然后是单词 END ,所以发生的情况是 Python 找到了单词“BEGIN”,然后是一个或多个字符直到换行符,作为一个字符不匹配。然后,Python 查找单词“END ”,由于没有找到,正则表达式不匹配任何内容。
如果希望正则表达式匹配跨多行的子字符串,需要传入 DOTALL 标志:
>>> mo = re.search('BEGIN (.*) END', s, re.DOTALL)
>>> print(mo.group())
BEGIN hello
world END
搜索多行字符串时不使用 MULTILINE 标志
在 UNIX 世界中,^和$被广泛理解为匹配一行的开始/结束,但是只有在设置了MULTILINE标志的情况下,Python 正则表达式才是这样。如果没有,它们将只匹配被搜索的整个字符串的开头/结尾。
>>> s = '''hello
>>> ... world'''
>>> print(re.findall(r'^\S+$', s))
[]
为了获得我们期望的行为,传入MULTILINE(或简称为M标志:
>>> print(re.findall(r'^\S+$', s, re.MULTILINE))
['hello', 'world']
不重复不贪婪
运算符*和+和?分别匹配 0 个或更多的、 1 个或更多的、 0 个或 1 个重复,默认情况下,它们是贪婪的(例如,它们试图匹配尽可能多的字符)。
一个典型的错误是试图使用这样的正则表达式来匹配 HTML 标签:<.+&>
这看起来很合理——匹配开始的<,然后一个或多个字符,然后结束的>——但是当我们在一些 HTML 上尝试时,会发生这样的情况:
>>> s = '<head> <style> blah </style> </head>'
>>> mo = re.search('<.+>', s)
>>> print(mo.group())
<head> <style> blah </style> </style>
发生的事情是 Python 已经匹配了开始的<,然后一个或多个字符(head),然后结束的>,但是它没有就此停止,而是尝试看看它是否可以做得更好,让.字符匹配更多的字符。事实上它可以,它可以匹配所有的东西,直到字符串最后的>,这就是为什么这个正则表达式最终匹配整个字符串。
解决这个问题的方法是在.操作符后面加上一个?字符,使其成为非贪婪的(例如,使其匹配尽可能少的字符)。
>>> mo = re.search('<.+?>', s)
>>> print(mo.group())
<head>
现在,当 Python 到达第一个>(它关闭了初始的标记)时,它会立即停止,而不是尝试看看是否能做得更好。
`## 不区分搜索的大小写
默认情况下,正则表达式区分大小写。例如:
>>> s = 'Hello World!'
>>> mo = re.search('world', s)
>>> print(mo)
None
为了使搜索不区分大小写,传入IGNORECASE标志:
>>> mo = re.search('world', s, re.IGNORECASE)
>>> print(mo.group())
World
不编译正则表达式
Python 做了大量工作来准备一个正则表达式,所以如果你要经常使用一个特定的正则表达式,首先编译它是值得的。
例如:
>>> myRegex = re.compile('...')
>>> # This reads the file line-by-line
>>> for lineBuf in open(testFilename, 'r'):
... print(myRegex.findall(lineBuf))
现在 Python 只做一次准备工作,然后在每次循环中重用预编译的正则表达式,从而节省了大量时间。`
Python 编程语言——基本特性和主要优势
无论现在有多少种编程语言在使用,其中哪一种是当今的领导者,Python 仍然是最爱之一。大多数软件开发人员在考虑将第二编程语言添加到简历中时都会选择 Python(以及 Python 开启的职业前景)。原因很简单——Python 确实很受欢迎,也很方便。由 Guido Van Rossum 在上个世纪(1991 年)创建的 Python 编码语言的目的是使编码更容易。它曾经只是 Perl 的替代品,但现在已经发展成为具有优秀代码可读性的通用语言。它允许开发人员用更少的步骤完成更多的工作,并且比 C++和 Java 简单。 Python 使用来自英语的关键词,甚至不需要深入的编程知识——一开始懂点数学就够了。简单性、开源性、种类繁多的库和令人印象深刻的范围使它成为目前世界上最流行的编程语言。
Python 的特性决定了它的受欢迎程度
免费和开源
可以从官网免费下载 Python。它的源代码对用户是可用的,你可以使用它并改进它。一个庞大的 Python 社区支持这种语言,并增强了它的编程特性,使它更加方便。
健壮库
如前所述,这种语言包括丰富的现成模块和函数库,经过测试和润色。使用 Python,您可以在任何需要的时候参考这些库,并通过使用现成的模块来节省时间。没有必要从头开始编写代码,因为您可以使用库元素。
面向对象
面向对象编程(OOP)是 Python 最重要的特性之一。它建议将数据和功能绑定成一个单元并一起工作。其余的代码不会访问数据。简而言之,这种方法简化了执行过程、协议等的系统。Python 支持所有的 OOP 概念,并允许程序员在创建新产品时充分利用这种语言。
高层
用 Python 编码时,开发人员不需要单独记住系统的架构。内存管理也不是必须的。Python 会处理它。
可扩展和集成
Python 代码可以写成 C 和 C++语言。此外,您可以成功地将 Python 与其他编程语言集成在一起。
便携性
这种编程语言兼容所有平台。相同的代码可以在 Windows、Linux 和 Mac 上正确运行。您不需要在代码中实现任何特定的更改来调整它以适应特定的平台。在任何设备上继续进行您的项目。
解读
当你执行 Python 代码时,它一行一行地工作,一次一行。因此,您可以轻松地调试代码。此外,语法是合乎逻辑的,代码总是比其他语言提供的代码行要少。
可扩展
在你开发了代码块的逻辑之后,你可以克隆这个逻辑并将其应用到其他模块,无论是大的还是小的。可以应用所有特征或仅选择选项。 这些只是 Python 众多功能中的一部分,正是这些功能使得这种编程语言如此出众,受到了来自世界各地的专家们的喜爱,包括https://jatapp . com/services/application-development-services/。它适用于网站、桌面和移动应用程序、游戏和其他产品。此外,它还是自动化、数据科学、人工智能和机器学习领域的默认选择。
Python 编程的主要优势
巨头谷歌将 Python 作为其主要语言之一。例如,YouTube 是基于 Python 的。Pinterest、Reddit、Instagram 都依赖 Python 编码语言。它被 IBM、英特尔、NASA、网飞、Spotify 和脸书使用。 当然,所有这些行业领袖选择这种语言是有原因的——或者有很多原因。有了这样优秀的市场参与者的支持,Python 才能蓬勃发展。 我们已经定义了这种编码语言的特征。现在,让我们回顾一下它们给工作、编程例程和具体挑战带来了哪些实际好处。
提高生产率
这里应该提到的是,Python 并不是该领域最快的编码语言。已经够快了。然而,它不如 Java 和 c。尽管如此,使用这种语言可以使程序员大大提高他们的生产率。解释很简单。Python 以其简洁性,花更少的时间编写产品代码。访问现成的模块和函数将让程序员节省时间并消除可能的错误。同时,Python 的整体功能允许用它创建的应用程序具有快速的性能。
原型的最佳选择
由于许多初创公司都涉及专用应用程序,编程语言的选择至关重要。他们的全功能原型必须很快准备好。创业公司很少是独特的。比竞争对手更早上市可以决定产品的命运。 在这样的情况下,Python 成为了最有利的选择。它提供了出色的流程控制,可以快速创建复杂的跨平台应用程序。此外,它还提供了自己的单元测试。如果你是一家为初创公司开发应用程序的公司,Python 将会是你语言列表中的首选。
最适合竞争性编程的选项
竞争性编程阶段是工作申请的一部分,候选人应该展示他们的实际编程技能。速度往往是这个过程中的决定因素。它可以定义申请者是否进入面试阶段。在这种情况下,Python 竞争性编程可能是最好的变体,即使您通常专攻不同的语言。Python 的功能性使其适用于解决任何任务。简洁的语法和更少的代码确保了出色的速度。如果你不得不写 5 行代码而不是 25 行,你会更快地完成任务。顺便说一下,Python 专家在市场上需求量很大,你可以期待有吸引力的工作机会。
GUI 支持
使用图形用户界面(GUI)的可能性通常定义了编程语言的用户友好性。以可视化格式编写代码总是更方便。它还让程序员更好地控制代码的正确性。Python 提供了几个方便的 GUI,开发人员可以导入和应用。
代码编写和格式标准
PEP 是 Python 代码编写的基本标准。它确保代码始终保持可读。如果你把一个项目转移给另一个开发者,用 Python 探索代码不会有任何问题。语法保持清晰简洁,没有不必要的元素和表达式。 工作程序只会受益于此,这也是 Python 受欢迎的最大原因之一。此外,它有助于程序员更好的自我组织。Python 鼓励他们从一开始就编写清晰准确的代码。程序员甚至会遇到从这种语言切换到其他编码语言的问题。它们追求同样的清晰和简洁,但是没有其他编程语言能达到同样的水平。
大量的教材
如果你决定在你的公司实施 Python,不会有任何困难。有许多英语和其他语言的书籍、教科书和文章。 除了文字资料,YouTube 上还有大量免费的视频指南。您可以找到个人开发者的视频日志、网络研讨会和会议的记录以及其他信息来源。添加来自世界各地的 Python 专家参与的奇妙社区。其实现在学 Python 比几年前简单多了。 尽管 Python 可能并不完美——它也有缺点——但所有专家都发现 Python 编程的好处要大得多。此外,这种语言是最新的,并在不断改进。毫无疑问,将来问题会得到解决或补偿。
结论
现代软件开发公司使用多种语言,但 Python 肯定是其中之一。功能性、多功能性和简洁性是 Python 的明显优势,受到了所有程序员的称赞。它甚至已经超过了 Java 和 C. 这样的霸主,所以,如果你正在考虑作为第二种开始或学习的编程语言,选择 Python,它永远不会让你失望。
开发者可以用于视频编辑的 3 大 Python 库
原文:https://www.pythoncentral.io/the-top-3-python-libraries-developers-can-use-for-video-editing/
如果您自己完成所有步骤而不使用库,视频编辑过程被认为是一项非常困难的任务。了解有助于使视频编辑过程更快更简单的库的更多信息。我们将讨论三个能够简化和改进视频编辑过程的库。
使用 MoviePy 编辑视频
MoviePy 库是使用 Python 编码的开发人员最常用的库。你可以在其中执行任何基本的操作,比如插入标题、剪切或合并片段、处理视频,甚至创建效果。
模块中的所有操作都可以用一行代码来执行。编码尽可能简单,即使对新手来说也很清楚。值得注意的是,该代码可以在任何计算机上运行,并且受任何版本的 Python 支持。要开始编辑,你应该立即在你的机器上安装 Python 。
该库简单易用。即使是初学者也能很容易地弄清楚工作的算法和代码。它允许你快速创建你的剪辑和效果,并与任何版本的 Python 和任何操作系统。
使用 Scikit 编辑视频-视频
普通用户依赖各种视频编辑软件:如果他们想要简单的编辑,他们下载 Windows 版的 iMovie或 macOS 版的视频编辑工具。另一方面,编码器可以使用 Scikit-Video 等库快速轻松地编辑视频。
Scikit-Video 库包括一整套不同的视频处理和编辑算法,了解这个库将有助于你更好地学习 Python。使用它,您可以评估帧中的运动,控制质量并应用必要的过滤器。
Scikit-Video 是作为图像编辑版本的附加软件开发的,它拥有处理视频的所有可能的算法。
视频和图像之间的算法是匹配的,并且一些度量可以应用于视频帧和图像。但尽管如此,有些算法只能应用于视频,比如降噪。这个库是所谓的各种算法的集合,这些算法可以用于视频,也可以不专门用于视频,但可以用于编辑视频。
使用 vcdgear 编辑视频
VidGear 库以其轻便易用而闻名。程序员只需填写所需的代码行,只需几个步骤就可以快速轻松地完成复杂的视频处理任务。
VidGear 是三大 Python 库之一,可以帮助您快速轻松地对视频进行调整。该库进行了很好的优化,因此,它给面临编辑视频剪辑任务的网页设计师和程序员留下了极好的印象。除了速度之外,VidGear 可以可靠地处理所有错误,并且有许多有吸引力的选项。
以 MoviePy 为例说明如何用 Python 库编辑视频
最受开发者欢迎的库是 MoviePy。要开始使用,您需要在您的计算机上安装它。该库有许多功能,对于面临视频编辑任务的程序员和开发人员来说是最快和最有吸引力的。我们来详细分解一下 MoviePy 可以执行的功能:
- 合并视频文件。要从几个文件中制作一个视频,你需要在行中输入代码,并从文件夹中选择你要合并的视频。
- 折叠视频剪辑。使用 MoviePy,可以将屏幕分割成多个部分,每个部分都会播放一个新的视频。为此,输入 Python 代码并从打开的文件夹中打开必要的文件。
- 添加转场。MoviePy 常用来给视频添加各种翻译。你只需要输入代码,添加必要的动画,同时指定时间间隔。
既然您已经熟悉了 MoviePy 库可以执行的功能,以及您可以使用哪些 Python 技巧,那么让我们来看一个如何使用这个库来修剪和合并剪辑的示例。这个过程越简单越好,现在你就自己看吧!
- 原视频看完后,可以使用内置的方法,做很多事情。
- 要连接视频片段,你需要使用一个视频子剪辑,它将帮助你返回剪辑的剪切部分。
- 之后,您应该输入代码,返回从 start_secondsend_seconds 开始的视频中剪切的视频片段,并将所有片段精简为一个。
- 当你完成所有这些动作后,你可以从修剪过的片段列表中选择你需要的,你就可以创建一个联合视频了。
你已经看到这个程序很简单,是创建视频内容的好帮手。MoviePy 库将帮助您处理任何复杂的视频处理任务,并帮助您快速有效地剪切、粘贴或处理特定的视频片段。只需几个简单的步骤,你就可以轻松地成为 Python 开发者,获得成功的视频,并对结果尽可能满意。
结论
现在,您已经熟悉了所有三个有助于视频编辑的库,您可以利用它们进行成功而快速的编辑。最流行的是 MoviePy,它被数百万程序员和开发者使用。请记住,编辑剪辑是一个非常负责任的过程,通常会非常耗时,多亏了这个 Python 库,您将能够立即处理任何任务。
我们已经证明,您不必成为 Python 专业人员,也可以用简单的代码创建成功的视频。库的一个主要优点是对每个用户来说都很简单和容易访问,不管这个人是专家还是初学者。
Python 的禅:卓越编程的哲学
原文:https://www.pythoncentral.io/the-zen-of-python-a-philosophy-of-programming-excellence/
Python 的禅宗是由 Python 的创始人之一 Tim Peters 记录的 19 个观察的集合。虽然最初的集锦有 20 条格言,但吉多·范·罗苏姆认为最后一条是彼得斯开的一个奇怪的玩笑。
这个集合在 2004 年被标准化为 PEP 20,因为它极大地影响了 Python 社区的编程过程。在编写代码时记住这些观察并不是强制性的,但是它确实有助于确保代码的质量。
Python 包含了一个复活节彩蛋,你可以通过在解释器上运行“import this”来读取格言列表。
在本帖中,我们将讨论这些格言的含义,以及它们如何帮助你改进代码。
Python 之禅:崩溃
#1 漂亮比难看好
程序员是解决问题的专家,但是由于编写、记录和维护 Python 代码通常是团队工作,简单地为问题设计解决方案是不够的。理想情况下,代码需要是可读的和优雅的。
但是是什么让代码变得“美丽”呢?就像生活中一样,在 Python 编程中,美是主观的。然而,经验法则是代码必须易于被任何开发人员理解。
换句话说,如果一个程序运行得很好,并不意味着它是美丽优雅的。去掉不必要的条件,简化你的解决方案,会让你的代码变得漂亮。
#2 显性比隐性好
阅读这个观察,你可以得出结论,这是不言自明的。但是许多人在编码时没有实现它。
这句格言背后的意思是写冗长的代码比写间接的代码更好。Python 程序员需要竭尽全力确保他们代码的功能不会隐藏在难以理解的语言后面。
简单地说,你必须写出另一个没有程序知识的程序员也能理解的代码。
#3 简单胜于复杂
晚饭后拿出一个压力清洗机来清洗碗碟可能是一种解决方法,但它可能会损坏盘子。更不用说,这是一个愚蠢的解决问题的方法。
同理,编写复杂的代码来解决简单的程序也是不切实际的。Python 程序员必须避免使他们的解决方案过于复杂,即使它们看起来很聪明并且有效。
使你的程序复杂化最终会造成更大的损害,你的团队不会欣赏这一点。
#4 复杂比复杂好
虽然用压力清洗机洗碗不切实际,但如果你在洗车,使用压力清洗机可能是正确的方法。
前面的观察和这个提醒程序员,对于同一个问题,既有简单的解决方案,也有复杂的解决方案。但就像你不会用压力清洗机洗碗一样,你也不会用小擦洗器洗车。
这句格言的意思是,在大多数情况下,重视简单胜过复杂可能是正确的做法。尽管如此,当简单的解决方案不切实际时,您最好实现复杂的解决方案。
简单来说,Python 程序员应该记住简单性的限度。
#5 平比嵌套好
程序员通常有一种将事物组织成类别和子类别的诀窍,以区分他们程序的功能。许多程序员认为这是值得的,因为有序比混乱好。
然而,用这种方式组织代码会比组织更混乱。这并不是说将所有代码放在一个顶层模块中是个坏主意。但是,当您添加更多的子类别时,代码会变得越来越复杂。
坚持扁平的结构是保持程序简单的最好方法。
#6 疏比密好
程序员经常觉得有必要用过于复杂的代码来强调他们的技能。在一行代码中完成复杂的任务背后有一种完整的文化。
这并不是说俏皮话不好。在某些情况下,这样写解决方案是合理的。也就是说,这句格言表明程序员永远不应该为了在一行代码中包含所有功能而牺牲可读性。
#7 可读性计数
对于 Python 来说,可读性应该是重中之重。程序员只需编写一次代码,但许多人可能会多次阅读代码。
每个 Python 开发者都需要考虑到这一点。避免删除函数名和变量名中的元音字母,以确保代码始终清晰。
#8 特例不足以违反规则
Python 程序员需要遵循的最佳实践并不缺乏。这句格言表明,遵循规范比按照自己的方式编写代码更好,因为不一致会使代码不可读且难以处理。
#9 虽然实用性战胜了纯粹性
你可以把这看作是前面观察的延伸。虽然遵循最佳实践总是更好的,但是仅仅为了遵守规则而付出额外的努力也会使代码不可读。
如果你解决问题的方法比最佳实践所指出的方法更容易理解、更实用,那么破例背离最佳实践是更明智的做法。
#10 个错误永远不会悄无声息地过去
当一个程序返回 None 或一个错误代码,并且没有引发异常时,这个错误被称为无声错误。
这句格言背后的思想是,程序崩溃比抛出一个无声的错误并继续运行要好。这是因为沉默错误可能会导致复杂的错误,修复这些错误将更具挑战性。
#11 除非明确静音
这是上一课的延伸。在某些情况下,程序员可能想忽略程序抛出的错误。在这些情况下,最好显式地隐藏错误。
#12 面对暧昧,拒绝猜测的诱惑
程序员首先要学习的一件事是,计算机只做用户指示它们做的事情。换句话说,如果你的程序没有像你期望的那样运行,它只是在执行你的指令,而你的解决方案中有一个失误。
通过尝试许多不同的方法来解决不想要的行为,直到找到合适的方法,这不是正确的策略。它可能会掩盖问题,而不是解决问题。
这句格言指出,你必须拒绝盲目尝试不同解决方案的诱惑。您需要慢慢地浏览代码,并思考创建必要解决方案的逻辑。
应该有一种——最好只有一种——显而易见的方法来做这件事
如果你熟悉 Perl 编程语言,你可能知道它的格言:“有不止一种方法可以做到这一点!”
但是这句格言忽略了有几个选择通常会导致选择过多。当 Python 程序员找到几种方法来编写实现相同目标的代码时,也会出现这种情况。
投入额外的工作去学习问题的每一个解决方案是没有必要的。这句格言要求程序员缩小显而易见的解决方案并实现它。
#14 尽管这种方式一开始可能并不明显,除非你是荷兰人
这一课反映了 Tim Peters 的幽默感,因为 Python 的创造者 van Rossum 是荷兰人。
这一课看似轻松,但强调了一个重要的事实——程序员可能无法理解和回忆一门语言的规则,除非他们创造了这门语言。
拥有初学者的心态是提高编程技能的关键。
#15 现在总比没有好
它的意思是,如果一个程序陷入无限循环、崩溃或挂起,那么它比没有陷入无限循环、崩溃或挂起的程序更糟糕。
#16 虽然永远也不会比现在好
这句格言表明,等待一个程序完成执行比提前终止程序并根据错误的结果做出反应要好。
#17 如果实现很难解释,那就是个坏主意
有些程序员认为,如果他们能理解自己的代码,代码就足够好了。然而,如前所述,编程是一项团队活动。
如果你不能很容易地向你的队友解释你的解决方案,很可能这个解决方案太复杂了。
#18 如果实现容易解释,可能是个好主意
对上一课的扩展,这一课说如果代码易于解释,并不表明代码是好是坏。
名称空间是一个非常棒的想法——让我们多做一些吧!
在这最后一句格言中,提到了名称空间,它是组织分配给对象的名称的抽象。
这一课要说的是 Python 组织符号名称的方式是惊人的。
为 Python 函数计时
在之前的一篇文章中(在 Python 中测量时间- time.time() vs time.clock() ),我们学习了如何使用模块timeit对程序进行基准测试。因为我们在那篇文章中计时的程序只包括原始语句而不是函数,所以我们将探索如何在 Python 中实际计时一个函数。
不带参数的 Python 函数计时
模块函数timeit.timeit(stmt, setup, timer, number)接受四个参数:
stmt哪个是你要衡量的语句;它默认为“通过”。setup是在运行stmt之前运行的代码;它默认为“通过”。- 哪一次?计时器对象;它通常有一个合理的默认值,所以你不必担心它。
number这是您希望运行stmt的执行次数。
其中timeit.timeit()函数返回执行代码所用的秒数。
现在假设你想测量一个函数costly_func,实现如下:
def costly_func():
return map(lambda x: x^2, range(10))
您可以使用 timeit 来测量它的执行时间:
>>> import timeit
>>> def costly_func():
... return map(lambda x: x^2, range(10))
...
>>> # Measure it since costly_func is a callable without argument
>>> timeit.timeit(costly_func)
2.547558069229126
>>> # Measure it using raw statements
>>> timeit.timeit('map(lambda x: x^2, range(10))')
2.3258371353149414
请注意,我们使用了两种方法来测量这个函数。第一种方式传入 Python 可调用函数costly_func,而第二种方式传入原始 Python 语句costly_func。虽然第一种方式的时间开销比第二种方式稍大,但我们通常更喜欢第一种方式,因为它可读性更好,也更容易维护。
用参数计时 Python 函数
我们可以使用 decorators 来度量带有参数的函数。假设我们的costly_func是这样定义的:
【python】
def cost _ func(lst):
返回映射(lambda x: x^2,lst)
您可以使用如下定义的装饰器来度量它:
【python】
def wrapper(func,args, * kwargs):
def wrapped():
return func(* args,**kwargs)
return wrapped
现在您使用这个装饰器将带参数的costly_func包装成不带参数的函数,以便将其传递给timeit.timeit。
>>> def wrapper(func, *args, **kwargs):
... def wrapped():
... return func(*args, **kwargs)
... return wrapped
...
>>> def costly_func(lst):
... return map(lambda x: x^2, lst)
...
>>> short_list = range(10)
>>> wrapped = wrapper(costly_func, short_list)
>>> timeit.timeit(wrapped, number=1000)
0.0032510757446289062
>>> long_list = range(1000)
>>> wrapped = wrapper(costly_func, long_list)
>>> timeit.timeit(wrapped, number=1000)
0.14835596084594727
计时来自另一个模块的 Python 函数
假设您在另一个模块mymodule中定义了函数costly_func,既然它不是本地可访问的,那么您如何测量它的时间呢?嗯,你可以把它导入到本地名称空间或者使用setup参数。
# mymodule.py
def costly_func():
return map(lambda x: x^2, range(1000))
>>> timeit.timeit('costly_func()', setup='from mymodule import costly_func', number=1000)
0.15768003463745117
# OR just import it in the local namespace
>>> from mymodule import costly_func
>>> timeit.timeit(costly_func, number=1000)
0.15358710289001465
总结和提示
在本文中,我们学习了如何使用timeit.timeit测量 Python 函数的执行时间。通常,我们更喜欢将 Python 函数作为可调用对象导入并传递到timeit.timeit中,因为这样更易于维护。此外,请记住,默认的执行次数是 1000000,对于某些复杂的函数,这可能会大大增加总执行时间。
Python开发:SQLAlchemy及相关知识详解



被折叠的 条评论
为什么被折叠?



