open cms 简介

2010年3月27日 星期六 by green tea iceam china

OpenCms是专业水平的开源网站内容管理系统。使用OpenCms很容易创建并且管理复杂的网站,而不需要专业的html的知识。 它使用模板布局页面,并且用一个类似于office的用户界面的WYSIWYG 编辑器帮助用户建立内容。做为一个开源软件,OpenCms 完全免费。

OpenCms是1999年发布的,瑞典互联网顾问Framfab支持它。Framfab在欧洲六个国家设有分支机构。德国Framfab是 OpenCms项目的主要发起人。对于OpenCms的咨询和支持可以在Framfab以及其他的欧洲公司(比如Alkacon)那里获得。美国的支持选 择就比较有限,但是所有的文件和培训资料都有英文版的。现在,OpenCms已经被LGT Bank of Lichtenstein、BP South Africa、和UNICEF Netherlands以及其他很多用户采用。按照Emmerich的观点,OpenCms适用于那些每天有150,000 PV(page view)的网站。

1. OpenCms概述

OpenCms基于JAVA和XML语言技术,因此它适合完全融入到现有的系统内部。OpenCms可以非常好的运行在一个完全的开源环境中(例 如:Linux、Apache、Tomcat、MySQL). 当然,也可以很好的运行于商业环境下(例如:Windows NT、IIS、BEA Weblogic、Oracle DB)。

opencms是一个企业级产品,面向jsp基础较好的用户,不建议生手使用;适用于大中型及超大规模应用,小型站点建设不建议用该程序。一句老 话:大炮打蚊子终究不如苍蝇拍好使。

  • OpenCms是一个WEB站点内容管理系统
  • OpenCms是真正的开放源代码软件
  • OpenCms使用LGPL许可
  • 无需许可费用
  • OpenCms能自由从项目站点 http://www.opencms.org下载
  • 特别适用于生成公司Web站点和Intranet
  • 适用于已有IT基础设施的中大型企业
  • 大多数特性是根据实际的客户需求开发的
  • 高度灵活和可定制
  • 使用了许多已验证的开源Java组件
  • 核心系统的开源开发由Alkacon软件牵头
  • 有活力的开发团体:订阅邮件列表超过1000
  • 广泛的商业支持:超过50个官方解决方案提供者,200个以上的WEB公司提供技术
  • 同等数量的可用文档:第一本关于OpenCms的图书已由团体成员编写,交互式的文档和示例

2. 软硬件需求

软件:运行环境如Linux + Tomcat + MySQL,Win NT + IIS + Tomcat + MS SQL,Solaris + BEA + Oracle。硬件:高度灵活,能运行在一台笔记本电脑上。标准配置是一般的Intel PC/2Ghz CPU/1GB RAM其它配置可以是SUN Sparc,集群配置。

基于默认组件(如:Tomcat、MySQL/Oracle)的安装采用向导,只需5分钟。

3. 技术特点

OpenCms做为最先进的CMS 解决方案,采用该技术有如下优点:

  • 直接从WEB站点的前台编辑内容
  • 自动在线/离线工作流
  • 灵活的内容资源
  • 集成全文搜索引擎
  • 所见即所得编辑非结构化内容
  • 结构化内容采用易于定义的基于XML的内容项目
  • 在一个应用中管理多个站点
  • 全文搜索支持PDF、Word、Excel文档资源
  • 为所有的存储资源均可进行配置
  • 基于时间的自动内容发布和过期
  • 完全支持统一编码内容
  • ACL(Access Control List 访问控制表)权限控制系统
  • 可选的HTML静态导出
  • 基于JSP的模版机制
  • 模块具有版本控制

基于Java/XML,能方便地集成到现有的硬/软件环境中。

易于安装,具有集成的HTML安装向导。

资源管理快捷、方便,支持几乎所有的文件类型,在编辑器中可通过拖放快速访问资源,并可设置不同的访问权限。

集成用户权限管理系统,由OpenCms控制所有内容的访问。

基于项目的发布,提供一个在同一服务器上包括离线工作/在线实况系统的工作环境。在项目发布前,修改内容可被浏览、确认和充分地测试。

具有强大的工作流和任务管理功能,对任务可设置用户组、优先等级、期限、首选用户。任务生命周期的每一阶段都有清晰记录以确保工作流的完整。

所见即所得的编辑功能,编辑页面无需HTML知识,同时一个集成的源代码编辑器让行家操纵HTML源代码。

国际化支持,支持统一的字符编码标准(UTF-8),能用国际化字符集处理本地化地内容,支持中文。

强大的内容版本控制功能,能让您追踪何时被谁修改的痕迹。所有历史版本都被存档,能够恢复,允许您随时访问历史版本。

支持多种模板机制,易于实现统一布局的站点设计。

OpenCms的Cache机制可随意地为动态创建的页面或页面变化提供高速缓存,来减少运行时从数据库的查询次数,大大提高站点的运行性能。

安全/SSL支持,通过Https协议保护全部或站点的一部分。任何资源能被标记为https,OpenCms将只给通过Https连接的请求提供 该资源。

计划任务系统,OpenCms提供一个集成计划任务系统。利用它,可周期性或某一个特定时间之后调用一个定制的动作。

应用服务器集成/EJB支持。运行OpenCms在一个J2EE环境(如BEA Weblogic)提供配置分式对象构架,特别是EJB技术。使用这些技术,W eb站点后台处理可以构架为分布式组件方式。根据J2EE应用模型的四层架构,表现与事务逻辑可以严格地分开。当内容数据部署到EJB时,OpenCms 关注表现数据,利用集成的JSP引擎创建通用的web站点布局。

支持负载均衡或失效恢复的集群。为了保证硬件故障时Web站点可用,或处理站点高负载,OpenCms可安装多个服务器的集群。当新的内容发布 时,OpenCms将自动更新集群中的服务器。

总之,OpenCms基于标准的Java技术,支持多种数据库和操作系统,易于适应大多数现有IT系统。

4. 选择OpenCms的理由

  • 考验
    已被遍布全球的大小机构/公司使用
  • 成熟
    开源开发始于2000年,目前版本为6.0
  • 易于使用
    所见即所得和直接编辑
  • 适应标准
    使用/实现成熟的API标准
  • 技术支持可利用
    全球超过50家企业注册为OpenCms的官方解决方案提供商
  • 节省费用
    与昂贵的付费商业非开源产品相比
  • 开源
    内容管理系统未来市场的稳固
  • 适合现有IT基础设置
    因为是Java,所以空间中立,能使用您现有的数据库(如Oracle)
  • 适合于自主开发的要求
  • 专家评论好

OpenCms最新版为OpenCms 7 RC1

OpenCms 7.0 RC 1可以从官方网站(www.opencms.org) 下载获得,源代码也可以从CVS中下载,标签为“build_7rc_1”。

OpenCms 7 RC1 的主要特性

  • 内容链接管理有了极大的提高。
  • 如果文件(或文件夹)被移动或重命名,则链接到此文件的资源会自动更新链接。
  • 删除一个资源时,会弹出确认对话框,显示了链接到此资源的相关资源。
  • 新增的“内容关系引擎”可以定义OpenCms资源之间任意的关系。
  • 增加了WebDAV访问OpenCms VFS的支持。
  • 编辑器中标准的HTML标签“area”、“object”和“embed”增加了对链接管理的支持。
  • 单独使用一个队列来进行资源的发布,用户在执行发布操作之后可以继续其它的工作。
  • 用户管理中增加了组织单位(OUs)的概念。
  • 系统权限的分配完全基于新增的角色组。
  • “组织单位”的增加允许组织单位的管理员单独对用户/用户组进行管理。
  • OpenCms工作区中为超级管理员组增加了“用户切换”的功能。
  • OpenCms工作区一些功能有了很大的发送,尤其是对其它用户加锁的控制。
  • OpenCms工作区中很多对话框采用了Ajax,响应速度更快。
  • 工作区中“弹出菜单”能够基于用户的权限单独进行配置。
  • 工作区中“弹出菜单”中增加了“恢复删除”的功能,可以对删除的资源(包括它下面的所有资源)进行恢复。
  • 全文搜索有了极大的提高,通过配置,可以直接对资源的属性或XML内容的字段进行搜索。
  • 工作区中新增“time warp”(我姑且先把它翻译为“时间隧道”)特性,允许用户“跳转”到某一特定时间,这样就可对设置了“终止日期”或“发布日期”的资源进行“真实时 间”的体验查看。
  • 当修改了已经存在实例资源的XML shcema时,这些结构化的XML内容会自动进行更新。
  • 工作区中增加了“搜索”工具,这对内容的管理有了很大的帮助。
  • 优化了核心的数据库结构。
  • 默认情况下JSP 2.0和Servlet 2.4。


--
software.zhouxinxin.com  车前草

济南大学调剂

2010年3月19日 星期五 by green tea iceam china

济南大学2010年研究生调剂信息(全公费)

  高校名称:济南大学

  所在省市:山东

  调剂专业:马克思主义基本原理,文艺学,控制理论与控制工程,中西医结合基础,计算机应用技术等

  是否有公费名额:有

  根据近几年的复试资格线,济南大学有如下专业预计需要调剂:

专业名称专业代码需调人数联系人、电话 备注
马克思主义基本原理0305012 周老师:0531-82766949
Yjs_zcm@ujn.edu.cn
公费
文艺学 0501011公费
应用数学 0701042公费
应用化学 0817044王老师:0531-82765474
chm_wangxj@ ujn.edu.cn
公费
工业催化0817052 公费
环境工程0830021 公费
化学工程43011711 公费
机械电子工程0802025 张老师:0531-89736314
me_zhangh@ ujn.edu.cn
公费
机械设计及理论 0802032公费
机械工程 43010210公费
材料科学与工程 0805006王老师:0531-82767357
mse_wangdz@ ujn.edu.cn
公费
材料工程4301058 公费
控制理论与控制工程0811016 王老师:0531-82765879
cse_wangpt@ ujn.edu.cn
公费
模式识别与智能系统 0811042公费
控制工程 43011111公费
信号与信息处理 0810022刘老师:0531-82767505
Jn_don@yahoo.cn
公费
计算机应用技术0812037 公费
计算机技术43011215 公费
结构工程0814023 周老师:0531-82766949
Yjs_zcm@ujn.edu.cn
公费
防灾减灾工程及防护工程 0814051公费
水文学及水资源0815015公费
技术经济及管理1202042公费
基础医学1001003安老师:0531-82919831
ykkyyjs@126.com
公费
临床医学 1002003公费
中西医结合基础 1006011公费
药物化学 1007011公费
微生物与生化药学 1007051公费
药理学 1007061公费
外科学(专业学位) 4502102公费

  凡报考上述专业且符合教育部划定的“A类考生复试分数线”均可申请向我校调剂,有意向者可与联系人联系。为方便考生调剂报考我校,现将我校2010年调剂工作的相关要求公告如下:

  一、 调剂原则

  1、初试成绩(单科与总成绩)达到国家统一划定的A类地区复试分数线;

  2、调剂专业为相同或相近专业,统考科目相同;

  3、先校内相近专业调剂,后省内、外相同或相近专业之间调剂。

  4、其余以教育部文件的规定为准。

  二、调剂程序

  1、通过上述联系方式同我校联系人联系,登记有关信息(信息包括:考生姓名、性别、毕业院校、学历、第一志愿单位、报考专业、考号、各科成绩及联系电话)。

  2、调剂的时间将在山东省研究生招生工作会议后确定并公告,请调剂考生随时关注我校研究生招生的相关通知。

  3、我校将在教育部规定时间内在中国研究生招生信息网(yz.chsi.com.cnyz.chsi.cn)的硕士研究生调剂服务系统中公布具体的生源余缺信息及调剂要求,凡调剂到我校的考生必须在该网站上按要求登录信息、提请申请,并按回复要求及时应答,我校最终以该网站上的相关调剂信息为准。

  4、调剂考生将随同我校一志愿上线生一起参加研究生复试,复试比例为1:1--1.2,综合初试复试成绩按专业排序从优录取。

  地址:济南市济微路106号 济南大学研究生招生办公室

  邮编:250022

  电话(传真): 0531-82765949


--
software.zhouxinxin.com  车前草

山科 调剂

by green tea iceam china

高校名称:山东科技大学

  所在省市:山东

  调剂专业:见下表

  是否有公费名额:未知

  根据成绩测算,2010年我校拟在部分专业接收调剂生。参照往年调剂政策,具体说明如下:

  一、对调剂考生的要求:

  1、调剂考生的各科初试成绩应高于拟调剂专业的全国一区初试合格资格线。

  2、工学、管理学专业要求初试科目含数学。

  3、相同或相近专业可调剂录取,其中统考科目须与拟调剂专业使用的统考试题相同。

  二、调剂专业范围

  1、学术型专业大体分布在采矿、安全、测绘、地质、计算机、化工、材料、外语和物理电子学等专业。上述专业有部分公费名额,先调剂者优先安排。

  2、我校MBA、法律硕士(法学)、法律硕士(非法学)、全日制工程硕士各领域接收调剂生,除MBA外全为公费,具体专业清单可见调剂专业列表。

  三、教育部开通网上调剂系统(http://yz.chsi.cnhttp://yz.chsi.com.cn),所有调剂考生在教育部研招网调剂系统上提交申请(以原报名时的用户名和密码),经我校审核同意后可参加复试。

  四、我校将及时通知审核通过的考生参加复试。复试时考生须携带有效身份证件、学历学位证书原件和准考证原件。调剂考生在复试录取前不得随意更改报考志愿,否则将会影响正常复试和录取。复试合格的考生,我校将调取其初试试卷。

  五、我校研究生招生办公室联系电话:0532-86057150 传真:0532-86057140 联系人:王老师。

  地址:青岛经济技术开发区前湾港路579号 邮编:266510

  Email:yjsyzsb@sdkd.net.cn

  六、调剂专业列表

学院名称

学术型专业

全日制专业学位类别或领域

资源与环境工程学院

系统理论、固体力学、工程力学、水文学及水资源、采矿工程、安全技术及工程

矿业工程、安全工程、工业工程

测绘科学与工程学院

地图学与地理信息系统、大地测量学与测量工程、摄影测量与遥感、地图制图学与地理信息工程

测绘工程

地质科学与工程学院

古生物学与地层学、矿产普查与勘探、地球探测与信息技术、地质工程

地质工程

土木建筑学院

建筑与土木工程

机械电子工程学院

机械工程、仪器仪表工程、物流工程

信息科学与工程学院

基础数学、计算数学、概率论与数理统计、应用数学、运筹学与控制论、电路与系统、计算机系统结构、计算机软件与理论、计算机应用技术、情报学

计算机技术、软件工程

经济管理学院

工商管理硕士

信息与电气工程学院

控制工程、电气工程、交通运输工程

化学与环境工程学院

化学工程、化学工艺、应用化学、矿物加工工程、环境工程

材料科学与工程学院

材料物理与化学、材料学、材料加工工程

材料工程

文法学院

法律硕士(法学)、法律硕士(非法学)

外国语学院

英语语言文学、外国语言学及应用语言学

理学院

物理电子学


--
software.zhouxinxin.com  车前草

it's a text

2010年3月15日 星期一 by green tea iceam china

23-6.

Microsoft Excel and Web Pages. Create an application that will read data from an Excel spreadsheet and map all of it to an equivalent HTML table. (You may use the third-party HTMLgen module if desired.)

23-7.

Microsoft Office Applications and Web Services. Interface to any existing Web service, whether REST- or URL-based, and write data to an Excel spreadsheet or format the data nicely into a Word document. Format them properly for printing. Extra Credit: Support both Excel and Word.

23-8.

Microsoft Outlook and Web Services. Similar to the previous problem, do the same thing, but put the data into a new e-mail message that you send with Outlook. Extra Credit: Do the same thing but send the e-mail with regular SMTP instead. (You may wish to refer to Chapter 17 on Internet Client Programming.)

23-9.

Microsoft PowerPoint. Design a presentation slide creator. Design the specification of a text file that users will create with Word or a normal text editor. Using the specification format, read in the presentation data and create the appropriate PowerPoint slides all as part of a single presentation.

23-10.

Microsoft Outlook, Databases, and Your Address Book.Write a program that will extract the contents of an Outlook address book and store the desired fields into a database. The database can be a text file, DBM file, or even an RDBMS. (You may wish to refer to Chapter 21, Database Programming.) Extra Credit: Do the reverse ... read in contact information from a database (or allow for direct user input) and create or update records in Outlook.

23-11.

Microsoft Outlook and E-mail. Develop a program that backs up your e-mail by taking the contents of your Inbox and/or other important folders and saves them in (as close to) regular "box" format to disk.

23-12.

Microsoft Outlook Calendar. Write a simple script that creates new Outlook appointments. Take at least the following as user input: start date and time, appointment name or subject, and duration of appointment.

23-13.

Microsoft Outlook Calendar. Build an application that dumps the contents of your appointments to a destination of your choice, i.e., to the screen, to a database, to Excel, etc. Extra Credit: Do the same thing to your set of Outlook tasks.

23-14.

Multithreading. Update the Excel version of the stock quote download script (estock.pyw) so that the downloads of data happen "concurrently" using multiple Python threads. Optional: You may also try this exercise with Visual C++ threads using win32process.beginthreadex().

23-15.

Excel Cell Formatting. In the spreadsheet version of the stock quote download script (estock.pyw), we saw in Figure 23-7 how the stock price does not default to two places after the decimal point even if we pass in a string with the trailing zero(s). When Excel converts it to a number, it uses the default setting for the number format.

  1. Change the numeric format to correctly go out to two decimal places by changing the cell's NumberFormat attribute to "0.00."

  2. We can also saw that the "change from previous close" column loses the "+" in addition to the decimal point formatting. However, we discover that making the correction in part (a) to both columns only solves the decimal place problem... the plus sign is automatically dropped for any number. The solution here is to change this column to be text instead of a number. You can do this by changing the cell's NumberFormat attribute to "@."

  3. By changing the cell's numeric format to text, however, we lose the right alignment that comes automatically with numbers. In addition to your solution to part (b), you must also now set the cell's HorizontalAlignment attribute to the Win32 Excel constant xlRight. After you come up with the solutions to all three parts, your output will now look more acceptable, as shown in Figure 23-9.

    Figure 23-9. Improving the Python-to-Excel stock quote script (estock.pyw)

Section 5.6.  Built-in and Factory Functions

2010年3月14日 星期日 by green tea iceam china

5.6. Built-in and Factory Functions

5.6.1. Standard Type Functions

In the last chapter, we introduced the cmp(), str(), and type() built-in functions that apply for all standard types. For numbers, these functions will compare two numbers, convert numbers into strings, and tell you a number's type, respectively. Here are some examples of using these functions:

>>> cmp(-6, 2)-1>>> cmp(-4.333333, -2.718281828)-1>>> cmp(0xFF, 255)0>>> str(0xFF)'255'>>> str(55.3e2)'5530.0'>>> type(0xFF)<type 'int'>>>> type(98765432109876543210L)<type 'long'>>>> type(2-1j)<type 'complex'>

5.6.2. Numeric Type Functions

Python currently supports different sets of built-in functions for numeric types. Some convert from one numeric type to another while others are more operational, performing some type of calculation on their numeric arguments.

Conversion Factory Functions

The int(), long(), float(), and complex() functions are used to convert from any numeric type to another. Starting in Python 1.5, these functions will also take strings and return the numerical value represented by the string. Beginning in 1.6, int() and long() accepted a base parameter (see below) for proper string conversionsit does not work for numeric type conversion.

A fifth function, bool(), was added in Python 2.2. At that time, it was used to normalize Boolean values to their integer equivalents of one and zero for true and false values. The Boolean type was added in Python 2.3, so true and false now had constant values of TRue and False (instead of one and zero). For more information on the Boolean type, see Section 5.7.1.

In addition, because of the unification of types and classes in Python 2.2, all of these built-in functions were converted into factory functions. Factory functions, introduced in Chapter 4, just means that these objects are now classes, and when you "call" them, you are just creating an instance of that class.

They will still behave in a similar way to the new Python user so it is probably something you do not have to worry about.

The following are some examples of using these functions:

>>> int(4.25555)4>>> long(42)42L>>> float(4)4.0>>> complex(4)(4+0j)>>>>>> complex(2.4, -8)(2.4-8j)>>>>>> complex(2.3e-10, 45.3e4)(2.3e-10+453000j)

Table 5.5 summarizes the numeric type factory functions.

Table 5.5. Numeric Type Factory Functions[a]

Class (Factory Function)

Operation

bool(obj)[b]

Returns the Boolean value of obj, e.g., the value of executing obj.__nonzero__()

int(obj, base=10)

Returns integer representation of string or number obj; similar to string.atoi(); optional base argument introduced in 1.6

long(obj, base=10)

Returns long representation of string or number obj; similar to string.atol(); optional base argument introduced in 1.6

float(obj)

Returns floating point representation of string or number obj; similar to string.atof()

complex(str) or complex(real, imag=0.0)

Returns complex number representation of str, or builds one given real (and perhaps imaginary) component(s)

[a] Prior to Python 2.3, these were all built-in functions.

[b] New in Python 2.2 as built-in function, converted to factory function in 2.3.

Operational

Python has five operational built-in functions for numeric types: abs(), coerce(), divmod(), pow(), and round(). We will take a look at each and present some usage examples.

abs() returns the absolute value of the given argument. If the argument is a complex number, then math.sqrt(num .real2 + num.imag2) is returned. Here are some examples of using the abs() built-in function:

>>> abs(-1)1>>> abs(10.)10.0>>> abs(1.2-2.1j)2.41867732449>>> abs(0.23 - 0.78)0.55

The coerce() function, although it technically is a numeric type conversion function, does not convert to a specific type and acts more like an operator, hence our placement of it in our operational built-ins section. In Section 5.5.1, we discussed numeric coercion and how Python performs that operation. The coerce() function is a way for the programmer to explicitly coerce a pair of numbers rather than letting the interpreter do it. This feature is particularly useful when defining operations for newly created numeric class types. coerce() just returns a tuple containing the converted pair of numbers. Here are some examples:

>>> coerce(1, 2)(1, 2)>>>>>> coerce(1.3, 134L)(1.3, 134.0)>>>>>> coerce(1, 134L)(1L, 134L)>>>>>> coerce(1j, 134L)(1j, (134+0j))>>>>>> coerce(1.23-41j, 134L)((1.23-41j), (134+0j))

The divmod() built-in function combines division and modulus operations into a single function call that returns the pair (quotient, remainder) as a tuple. The values returned are the same as those given for the classic division and modulus operators for integer types. For floats, the quotient returned is math.floor(num1/num2) and for complex numbers, the quotient is math.floor((num1/num2).real).

>>> divmod(10,3)(3, 1)>>> divmod(3,10)(0, 3)>>> divmod(10,2.5)(4.0, 0.0)>>> divmod(2.5,10)(0.0, 2.5)>>> divmod(2+1j, 0.5-1j)(0j, (2+1j))

Both pow() and the double star ( ** ) operator perform exponentiation; however, there are differences other than the fact that one is an operator and the other is a built-in function.

The ** operator did not appear until Python 1.5, and the pow() built-in takes an optional third parameter, a modulus argument. If provided, pow() will perform the exponentiation first, then return the result modulo the third argument. This feature is used for cryptographic applications and has better performance than pow(x,y) % z since the latter performs the calculations in Python rather than in C-like pow(x, y, z).

>>> pow(2,5)32>>>s>>> pow(5,2)25>>> pow(3.141592,2)9.86960029446>>>>>> pow(1+1j, 3)(-2+2j)

The round() built-in function has a syntax of round(flt,ndig=0). It normally rounds a floating point number to the nearest integral number and returns that result (still) as a float. When the optional ndig option is given, round() will round the argument to the specific number of decimal places.

>>> round(3)3.0>>> round(3.45)3.0>>> round(3.4999999)3.0>>> round(3.4999999, 1)3.5>>> import math>>> for eachNum in range(10):...           print round(math.pi, eachNum)...3.03.13.143.1423.14163.141593.1415933.14159273.141592653.1415926543.1415926536>>> round(-3.5)-4.0>>> round(-3.4)-3.0>>> round(-3.49)-3.0>>> round(-3.49, 1)-3.5

Note that the rounding performed by round() moves away from zero on the number line, i.e., round(.5) goes to 1 and round(-.5) goes to -1. Also, with functions like int(), round(), and math.floor(), all may seem like they are doing the same thing; it is possible to get them all confused. Here is how you can differentiate among these:

  • int() chops off the decimal point and everything after (aka truncation).

  • floor() rounds you to the next smaller integer, i.e., the next integer moving in a negative direction (toward the left on the number line).

  • round() (rounded zero digits) rounds you to the nearest integer period.

Here is the output for four different values, positive and negative, and the results of running these three functions on eight different numbers. (We reconverted the result from int() back to a float so that you can visualize the results more clearly when compared to the output of the other two functions.)

>>> import math>>> for eachNum in (.2, .7, 1.2, 1.7, -.2, -.7, -1.2, -1.7):...     print "int(%.1f)\t%+.1f" % (eachNum, float(int(eachNum)))...     print "floor(%.1f)\t%+.1f" % (eachNum,...     math.floor(eachNum))...     print "round(%.1f)\t%+.1f" % (eachNum, round(eachNum))...     print '-' * 20...int(0.2)     +0.0floor(0.2)   +0.0round(0.2)   +0.0--------------------int(0.7)     +0.0floor(0.7)   +0.0round(0.7)   +1.0--------------------int(1.2)     +1.0floor(1.2)   +1.0round(1.2)   +1.0--------------------int(1.7)     +1.0floor(1.7)   +1.0round(1.7)   +2.0--------------------int(-0.2)    +0.0floor(-0.2)  -1.0round(-0.2)  +0.0--------------------int(-0.7)    +0.0floor(-0.7)  -1.0round(-0.7)  -1.0--------------------int(-1.2)    -1.0floor(-1.2)  -2.0round(-1.2)  -1.0--------------------int(-1.7)    -1.0floor(-1.7)  -2.0round(-1.7)  -2.0

Table 5.6 summarizes the operational functions for numeric types.

Table 5.6. Numeric Type Operational Built-in Functions[a]

Function

Operation

abs(num)

Returns the absolute value of num

coerce(num1, num2)

Converts num1 and num2 to the same numeric type and returns the converted pair as a tuple

divmod(num1, num2)

Division-modulo combination returns (num1 / num2, num1 % num2) as a tuple; for floats and complex, the quotient is rounded down (complex uses only real component of quotient)

pow(num1, num2, mod=1)

Raises num1 to num2 power, quantity modulo mod if provided

round(flt, ndig=0)

(Floats only) takes a float flt and rounds it to ndig digits, defaulting to zero if not provided

[a] Except for round(), which applies only to floats.

5.6.3. Integer-Only Functions

In addition to the built-in functions for all numeric types, Python supports a few that are specific only to integers (plain and long). These functions fall into two categories, base presentation with hex() and oct(), and ASCII conversion featuring chr() and ord().

Base Representation

As we have seen before, Python integers automatically support octal and hexadecimal representations in addition to the decimal standard. Also, Python has two built-in functions that return string representations of an integer's octal or hexadecimal equivalent. These are the oct() and hex() built-in functions, respectively. They both take an integer (in any representation) object and return a string with the corresponding value. The following are some examples of their usage:

>>> hex(255)'0xff'>>> hex(23094823l)'0x1606627L'>>> hex(65535*2)'0x1fffe'>>>>>> oct(255)'0377'>>> oct(23094823l)'0130063047L'>>> oct(65535*2)'0377776'
ASCII Conversion

Python also provides functions to go back and forth between ASCII (American Standard Code for Information Interchange) characters and their ordinal integer values. Each character is mapped to a unique number in a table numbered from 0 to 255. This number does not change for all computers using the ASCII table, providing consistency and expected program behavior across different systems. chr() takes a single-byte integer value and returns a one-character string with the equivalent ASCII character. ord() does the opposite, taking a single ASCII character in the form of a string of length one and returns the corresponding ASCII value as an integer:

>>> ord('a')97>>> ord('A')65>>> ord('0')48>>> chr(97)'a'>>> chr(65L)'A'>>> chr(48)'0'

Table 5.7 shows all built-in functions for integer types.

Table 5.7. Integer Type Built-in Functions

Function

Operation

hex(num)

Converts num to hexadecimal and returns as string

oct(num)

Converts num to octal and returns as string

chr(num)

Takes ASCII value num and returns ASCII character as string; 0 <= num <= 255 only

ord(chr)

Takes ASCII or Unicode chr (string of length 1) and returns corresponding ordinal ASCII value or Unicode code point, respectively

unichr(num)

Takes a Unicode code point value num and returns its Unicode character as a Unicode string; valid range depends on whether your Python was built as UCS-2 or UCS-4

Previous Page
Next Page

Section 5.5.  Operators

by green tea iceam china

Section 5.5.  Operators
Previous Page
Next Page

5.5. Operators

Numeric types support a wide variety of operators, ranging from the standard type of operators to operators created specifically for numbers, and even some that apply to integer types only.

5.5.1. Mixed-Mode Operations

It may be hard to remember, but when you added a pair of numbers in the past, what was important was that you got your numbers correct. Addition using the plus ( + ) sign was always the same. In programming languages, this may not be as straightforward because there are different types of numbers.

When you add a pair of integers, the + represents integer addition, and when you add a pair of floating point numbers, the + represents double-precision floating point addition, and so on. Our little description extends even to non-numeric types in Python. For example, the + operator for strings represents concatenation, not addition, but it uses the same operator! The point is that for each data type that supports the + operator, there are different pieces of functionality to "make it all work," embodying the concept of overloading.

Now, we cannot add a number and a string, but Python does support mixed mode operations strictly between numeric types. When adding an integer and a float, a choice has to be made as to whether integer or floating point addition is used. There is no hybrid operation. Python solves this problem using something called numeric coercion. This is the process whereby one of the operands is converted to the same type as the other before the operation. Python performs this coercion by following some basic rules.

To begin with, if both numbers are the same type, no conversion is necessary. When both types are different, a search takes place to see whether one number can be converted to the other's type. If so, the operation occurs and both numbers are returned, one having been converted. There are rules that must be followed since certain conversions are impossible, such as turning a float into an integer, or converting a complex number to any non-complex number type.

Coercions that are possible, however, include turning an integer into a float (just add ".0") or converting any non-complex type to a complex number (just add a zero imaginary component, e.g., "0j"). The rules of coercion follow from these two examples: integers move toward float, and all move toward complex. The Python Language Reference Guide describes the coerce() operation in the following manner.

  • If either argument is a complex number, the other is converted to complex;

  • Otherwise, if either argument is a floating point number, the other is converted to floating point;

  • Otherwise, if either argument is a long, the other is converted to long;

  • Otherwise, both must be plain integers and no conversion is necessary (in the upcoming diagram, this describes the rightmost arrow).

The flowchart shown in Figure 5-1 illustrates these coercion rules.

Figure 5-1. Numeric coercion


Automatic numeric coercion makes life easier for the programmer because he or she does not have to worry about adding coercion code to his or her application. If explicit coercion is desired, Python does provide the coerce() built-in function (described later in Section 5.6.2).

The following is an example showing you Python's automatic coercion. In order to add the numbers (one integer, one float), both need to be converted to the same type. Since float is the superset, the integer is coerced to a float before the operation happens, leaving the result as a float:

>>> 1 + 4.55.5

5.5.2. Standard Type Operators

The standard type operators discussed in Chapter 4 all work as advertised for numeric types. Mixed-mode operations, described above, are those which involve two numbers of different types. The values are internally converted to the same type before the operation is applied.

Here are some examples of the standard type operators in action with numbers:

>>> 5.2 == 5.2True>>> -719 >= 833False>>> 5+4e >= 2-3eTrue>>> 2 < 5 < 9      # same as ( 2 < 5 )and ( 5 < 9 )True>>> 77 > 66 == 66    # same as ( 77 > 66 )and ( 66 == 66 )True>>> 0. < -90.4 < 55.3e2 != 3 < 181False>>> (-1 < 1) or (1 < -1)True

5.5.3. Numeric Type (Arithmetic) Operators

Python supports unary operators for no change and negation, + and -, respectively; and binary arithmetic operators +, -, *, /, %, and **, for addition, subtraction, multiplication, division, modulo, and exponentiation, respectively. In addition, there is a new division operator, //, as of Python 2.2.

Division

Those of you coming from the C world are intimately familiar with classic divisionthat is, for integer operands, floor division is performed, while for floating point numbers, real or true division is the operation. However, for those who are learning programming for the first time, or for those who rely on accurate calculations, code must be tweaked in a way to obtain the desired results. This includes casting or converting all values to floats before performing the division.

The decision has been made to change the division operator in some future version of Python from classic to true division and add another operator to perform floor division. We now summarize the various division types and show you what Python currently does, and what it will do in the future.

Classic Division

When presented with integer operands, classic division truncates the fraction, returning an integer (floor division). Given a pair of floating-point operands, it returns the actual floating-point quotient (true division). This functionality is standard among many programming languages, including Python. Example:

>>> 1 / 2               # perform integer result (floor)0>>> 1.0 / 2.0           # returns actual quotient0.5

True Division

This is where division always returns the actual quotient, regardless of the type of the operands. In a future version of Python, this will be the algorithm of the division operator. For now, to take advantage of true division, one must give the from__future__import division directive. Once that happens, the division operator ( / ) performs only true division:

>>> from __future__ import division>>>>>> 1 / 2              # returns real quotient0.5>>> 1.0 / 2.0          # returns real quotient0.5

Floor Division

A new division operator ( // ) has been created that carries out floor division: it always truncates the fraction and rounds it to the next smallest whole number toward the left on the number line, regardless of the operands' numeric types. This operator works starting in 2.2 and does not require the __future__ directive above.

>>> 1 // 2     # floors result, returns integer0>>> 1.0 // 2.0 # floors result, returns float0.0>>> -1 // 2    # move left on number line-1

There were strong arguments for as well as against this change, with the former from those who want or need true division versus those who either do not want to change their code or feel that altering the division operation from classic division is wrong.

This change was made because of the feeling that perhaps Python's division operator has been flawed from the beginning, especially because Python is a strong choice as a first programming language for people who aren't used to floor division. One of van Rossum's use cases is featured in his "What's New in Python 2.2" talk:

def velocity(distance, totalTime):    rate = distance / totalTime

As you can tell, this function may or may not work correctly and is solely dependent on at least one argument being a floating point value. As mentioned above, the only way to ensure the correct value is to cast both to floats, i.e., rate = float(distance) / float(totalTime). With the upcoming change to true division, code like the above can be left as is, and those who truly desire floor division can use the new double-slash ( // ) operator.

Yes, code breakage is a concern, and the Python team has created a set of scripts that will help you convert your code to using the new style of division. Also, for those who feel strongly either way and only want to run Python with a specific type of division, check out the -Qdivision_style option to the interpreter. An option of -Qnew will always perform true division while -Qold (currently the default) runs classic division. You can also help your users transition to new division by using -Qwarn or -Qwarnall.

More information about this big change can be found in PEP 238. You can also dig through the 2001 comp.lang.python archives for the heated debates if you are interested in the drama. Table 5.2 summarizes the division operators in the various releases of Python and the differences in operation when you import new division functionality.

Table 5.2. Division Operator Functionality

Operator

2.1.x and Older

2.2 and Newer (No Import)

2.2 and Newer (Import of division)

/

classic

classic

true

//

n/a

floor

floor


Modulus

Integer modulo is straightforward integer division remainder, while for float, it is the difference of the dividend and the product of the divisor and the quotient of the quantity dividend divided by the divisor rounded down to the closest integer, i.e.,x - (math.floor(x/y) * y), or

For complex number modulo, take only the real component of the division result, i.e., x - (math.floor((x/y).real) * y).

Exponentiation

The exponentiation operator has a peculiar precedence rule in its relationship with the unary operators: it binds more tightly than unary operators to its left, but less tightly than unary operators to its right. Due to this characteristic, you will find the ** operator twice in the numeric operator charts in this text. Here are some examples:

>>> 3 ** 29>>> -3 ** 2       # ** binds tighter than - to its left-9>>> (-3) ** 2     # group to cause - to bind first9>>> 4.0 ** -1.0   # ** binds looser than - to its right0.25

In the second case, it performs 3 to the power of 2 (3-squared) before it applies the unary negation. We need to use the parentheses around the "-3" to prevent this from happening. In the final example, we see that the unary operator binds more tightly because the operation is 1 over quantity 4 to the first power ¼1 or ¼. Note that 1 / 4 as an integer operation results in an integer 0, so integers are not allowed to be raised to a negative power (it is a floating point operation anyway), as we will show here:

>>> 4 ** -1Traceback (innermost last):  File "<stdin>", line 1, in ?ValueError: integer to the negative power

Summary

Table 5.3 summarizes all arithmetic operators, in shaded hierarchical order from highest-to-lowest priority. All the operators listed here rank higher in priority than the bitwise operators for integers found in Section 5.5.4.

Table 5.3. Numeric Type Arithmetic Operators

Arithmetic Operator

Function

expr1 ** expr2

expr1 raised to the power of expr2[a]

+expr

(unary) expr sign unchanged

-expr

(unary) negation of expr

expr1 ** expr2

expr1 raised to the power of expr2[a]

expr1 * expr2

expr1 times expr2

expr1 / expr2

expr1 divided by expr2 (classic or true division)

expr1 // expr2

expr1 divided by expr2 (floor division [only])

expr1 % expr2

expr1 modulo expr2

expr1 + expr2

expr1 plus expr2

expr1 - expr2

expr1 minus expr2


[a] ** binds tighter than unary operators to its left and looser than unary operators to its right.

Here are a few more examples of Python's numeric operators:

>>> -442 - 77-519>>>>>> 4 ** 364>>>>>> 4.2 ** 3.298.7183139527>>> 8 / 32>>> 8.0 / 3.02.66666666667>>> 8 % 32>>> (60. - 32.) * ( 5. / 9. )15.5555555556>>> 14 * 0x0456>>> 0170 / 430>>> 0x80 + 0777639>>> 45L * 22L990L>>> 16399L + 0xA94E8L709879L>>> -2147483648L - 52147483648L-54294967296L>>> 64.375+1j + 4.23-8.5j(68.605-7.5j)>>> 0+1j ** 2          # same as 0+(lj**2)(-1+0j)>>> 1+1j ** 2          # same as 1+(lj**2)0j>>> (1+1j) ** 22j

Note how the exponentiation operator is still higher in priority than the binding addition operator that delimits the real and imaginary components of a complex number. Regarding the last example above, we grouped the components of the complex number together to obtain the desired result.

5.5.4. *Bit Operators (Integer-Only)

Python integers may be manipulated bitwise and the standard bit operations are supported: inversion, bitwise AND, OR, and exclusive OR (aka XOR), and left and right shifting. Here are some facts regarding the bit operators:

  • Negative numbers are treated as their 2's complement value.

  • Left and right shifts of N bits are equivalent to multiplication and division by (2 ** N) without overflow checking.

  • For longs, the bit operators use a "modified" form of 2's complement, acting as if the sign bit were extended infinitely to the left.

The bit inversion operator ( ~ ) has the same precedence as the arithmetic unary operators, the highest of all bit operators. The bit shift operators ( << and >> ) come next, having a precedence one level below that of the standard plus and minus operators, and finally we have the bitwise AND, XOR, and OR operators (&, ^, | ), respectively. All of the bitwise operators are presented in the order of descending priority in Table 5.4.

Table 5.4. Integer Type Bitwise Operators

Bitwise Operator

Function

~num

(unary) invert the bits of num, yielding -(num + 1)

num1 << num2

num1 left shifted by num2 bits

num1 >> num2

num1 right shifted by num2 bits

num1 & num2

num1 bitwise AND with num2

num1 ^ num2

num1 bitwise XOR (exclusive OR) with num2

num1 | num2

num1 bitwise OR with num2


Here we present some examples using the bit operators using 30 (011110), 45 (101101), and 60 (111100):

>>> 30 & 4512>>> 30 | 4563>>> 45 & 6044>>> 45 | 6061>>> ~30-31>>> ~45-46>>> 45 << 190>>> 60 >> 215>>> 30 ^ 4551


Previous Page
Next Page

Section 4.8.  Categorizing the Standard Types

by green tea iceam china

Section 4.8.  Categorizing the Standard Types
Previous Page
Next Page

4.8. Categorizing the Standard Types

If we were to be maximally verbose in describing the standard types, we would probably call them something like Python's "basic built-in data object primitive types."

  • "Basic," indicating that these are the standard or core types that Python provides

  • "Built-in," due to the fact that these types come by default in Python

  • "Data," because they are used for general data storage

  • "Object," because objects are the default abstraction for data and functionality

  • "Primitive," because these types provide the lowest-level granularity of data storage

  • "Types," because that's what they are: data types!

However, this description does not really give you an idea of how each type works or what functionality applies to them. Indeed, some of them share certain characteristics, such as how they function, and others share commonality with regard to how their data values are accessed. We should also be interested in whether the data that some of these types hold can be updated and what kind of storage they provide.

There are three different models we have come up with to help categorize the standard types, with each model showing us the interrelationships between the types. These models help us obtain a better understanding of how the types are related, as well as how they work.

4.8.1. Storage Model

The first way we can categorize the types is by how many objects can be stored in an object of this type. Python's types, as well as types from most other languages, can hold either single or multiple values. A type which holds a single literal object we will call atomic or scalar storage, and those which can hold multiple objects we will refer to as container storage. (Container objects are also referred to as composite or compound objects in the documentation, but some of these refer to objects other than types, such as class instances.) Container types bring up the additional issue of whether different types of objects can be stored. All of Python's container types can hold objects of different types. Table 4.6 categorizes Python's types by storage model.

Table 4.6. Types Categorized by the Storage Model

Storage Model Category

Python Types That Fit Category

Scalar/atom

Numbers (all numeric types), strings (all are literals)

Container

Lists, tuples, dictionaries


Although strings may seem like a container type since they "contain" characters (and usually more than one character), they are not considered as such because Python does not have a character type (see Section 4.8). Thus strings are self-contained literals.

4.8.2. Update Model

Another way of categorizing the standard types is by asking the question, "Once created, can objects be changed, or can their values be updated?" When we introduced Python types early on, we indicated that certain types allow their values to be updated and others do not. Mutable objects are those whose values can be changed, and immutable objects are those whose values cannot be changed. Table 4.7 illustrates which types support updates and which do not.

Table 4.7. Types Categorized by the Update Model

Update Model Category

Python Types That Fit Category

Mutable

Lists, dictionaries

Immutable

Numbers, strings, tuples


Now after looking at the table, a thought that must immediately come to mind is, "Wait a minute! What do you mean that numbers and strings are immutable? I've done things like the following":

x = 'Python numbers and strings'x = 'are immutable?!? What gives?'i = 0i = i + 1

"They sure as heck don't look immutable to me!" That is true to some degree, but looks can be deceiving. What is really happening behind the scenes is that the original objects are actually being replaced in the above examples. Yes, that is right. Read that again.

Rather than referring to the original objects, new objects with the new values were allocated and (re)assigned to the original variable names, and the old objects were garbage-collected. One can confirm this by using the id() BIF to compare object identities before and after such assignments.

If we added calls to id() in our example above, we may be able to see that the objects are being changed, as below:

>>> x = 'Python numbers and strings'>>> print id(x)16191392>>> x = 'are immutable?!? What gives?'>>> print id(x)16191232>>> i = 0>>> print id(i)7749552>>> i = i + 1>>> print id(i)7749600

Your mileage will vary with regard to the object IDs as they will differ between executions. On the flip side, lists can be modified without replacing the original object, as illustrated in the code below:

>>> aList = ['ammonia', 83, 85, 'lady']>>> aList['ammonia', 83, 85, 'lady']>>>>>> aList[2]85>>>>>> id(aList)135443480>>>>>> aList[2] = aList[2] + 1>>> aList[3] = 'stereo'>>> aList['ammonia', 83, 86, 'stereo']>>>>>> id(aList)135443480>>>>>> aList.append('gaudy')>>> aList.append(aList[2] + 1)>>> aList['ammonia', 83, 86, 'stereo', 'gaudy', 87]>>>>>> id(aList)135443480

Notice how for each change, the ID for the list remained the same.

4.8.3. Access Model

Although the previous two models of categorizing the types are useful when being introduced to Python, they are not the primary models for differentiating the types. For that purpose, we use the access model. By this, we mean, how do we access the values of our stored data? There are three categories under the access model: direct, sequence, and mapping. The different access models and which types fall into each respective category are given in Table 4.8.

Table 4.8. Types Categorized by the Access Model

Access Model Category

Types That Fit Category

Direct

Numbers

Sequence

Strings, lists, tuples

Mapping

Dictionaries


Direct types indicate single-element, non-container types. All numeric types fit into this category.

Sequence types are those whose elements are sequentially accessible via index values starting at 0. Accessed items can be either single elements or in groups, better known as slices. Types that fall into this category include strings, lists, and tuples. As we mentioned before, Python does not support a character type, so, although strings are literals, they are a sequence type because of the ability to access substrings sequentially.

Mapping types are similar to the indexing properties of sequences, except instead of indexing on a sequential numeric offset, elements (values) are unordered and accessed with a key, thus making mapping types a set of hashed key-value pairs.

We will use this primary model in the next chapter by presenting each access model type and what all types in that category have in common (such as operators and BIFs), then discussing each Python standard type that fits into those categories. Any operators, BIFs, and methods unique to a specific type will be highlighted in their respective sections.

So why this side trip to view the same data types from differing perspectives? Well, first of all, why categorize at all? Because of the high-level data structures that Python provides, we need to differentiate the "primitive" types from those that provide more functionality. Another reason is to be clear on what the expected behavior of a type should be. For example, if we minimize the number of times we ask ourselves, "What are the differences between lists and tuples again?" or "What types are immutable and which are not?" then we have done our job. And finally, certain categories have general characteristics that apply to all types in a certain category. A good craftsman (and craftswoman) should know what is available in his or her toolboxes.

The second part of our inquiry asks, "Why all these different models or perspectives"? It seems that there is no one way of classifying all of the data types. They all have crossed relationships with each other, and we feel it best to expose the different sets of relationships shared by all the types. We also want to show how each type is unique in its own right. No two types map the same across all categories. (Of course, all numeric subtypes do, so we are categorizing them together.) Finally, we believe that understanding all these relationships will ultimately play an important implicit role during development. The more you know about each type, the more you are apt to use the correct ones in the parts of your application where they are the most appropriate, and where you can maximize performance.

We summarize by presenting a cross-reference chart (see Table 4.9) that shows all the standard types, the three different models we use for categorization, and where each type fits into these models.

Table 4.9. Categorizing the Standard Types

Data Type

Storage Model

Update Model

Access Model

Numbers

Scalar

Immutable

Direct

Strings

Scalar

Immutable

Sequence

Lists

Container

Mutable

Sequence

Tuples

Container

Immutable

Sequence

Dictionaries

Container

Mutable

Mapping



Previous Page
Next Page

Section 4.6.  Standard Type Built-in Functions

by green tea iceam china

Section 4.6.  Standard Type Built-in Functions
Previous Page
Next Page

4.6. Standard Type Built-in Functions

Along with generic operators, which we have just seen, Python also provides some BIFs that can be applied to all the basic object types: cmp(),repr(),str(),type(), and the single reverse or back quotes (``) operator, which is functionally equivalent to repr().

Table 4.4. Standard Type Built-in Functions

Function

Operation

cmp(obj1, obj2)

Compares obj1 and obj2, returns integer i where:

 

i < 0 if obj1 < obj2

 

i > 0 if obj1 > obj2

 

i == 0 if obj1 == obj2

repr(obj) or `obj`

Returns evaluatable string representation of obj

str(obj)

Returns printable string representation of obj

type(obj)

Determines type of obj and return type object


4.6.1. type()

We now formally introduce type(). In Python versions earlier than 2.2, type() is a BIF. Since that release, it has become a "factory function." We will discuss these later on in this chapter, but for now, you may continue to think of type() as a BIF. The syntax for type() is:

  type(object)type() takes an object and returns its type. The return value is a type object.  >>> type(4)                                    # int type  <type 'int'>  >>>  >>> type('Hello World!')                     # string type  <type 'string'>  >>>  >>> type(type(4))                              # type type  <type 'type'>

In the examples above, we take an integer and a string and obtain their types using the type() BIF; in order to also verify that types themselves are types, we call type() on the output of a type() call.

Note the interesting output from the type() function. It does not look like a typical Python data type, i.e., a number or string, but is something enclosed by greater-than and less-than signs. This syntax is generally a clue that what you are looking at is an object. Objects may implement a printable string representation; however, this is not always the case. In these scenarios where there is no easy way to "display" an object, Python "pretty-prints" a string representation of the object. The format is usually of the form: <object_something_or_another>. Any object displayed in this manner generally gives the object type, an object ID or location, or other pertinent information.

4.6.2. cmp()

The cmp() BIF CoMPares two objects, say, obj1 and obj2, and returns a negative number (integer) if obj1 is less than obj2, a positive number if obj1 is greater than obj2, and zero if obj1 is equal to obj2. Notice the similarity in return values as C's strcmp(). The comparison used is the one that applies for that type of object, whether it be a standard type or a user-created class; if the latter, cmp() will call the class's special __cmp__() method. More on these special methods in Chapter 13, on Python classes. Here are some samples of using the cmp() BIF with numbers and strings.

>>> a, b = -4, 12>>> cmp(a,b)-1>>> cmp(b,a)1>>> b = -4>>> cmp(a,b)0>>>>>> a, b = 'abc', 'xyz'>>> cmp(a,b)-23>>> cmp(b,a)23>>> b = 'abc'>>> cmp(a,b)0

We will look at using cmp() with other objects later.

4.6.3. str() and repr() (and `` Operator)

The str() STRing and repr() REPResentation BIFs or the single back or reverse quote operator ( `` ) come in very handy if the need arises to either re-create an object through evaluation or obtain a human-readable view of the contents of objects, data values, object types, etc. To use these operations, a Python object is provided as an argument and some type of string representation of that object is returned. In the examples that follow, we take some random Python types and convert them to their string representations.

>>> str(4.53-2j)'(4.53-2j)'>>>>>> str(1)'1'>>>>>> str(2e10)'20000000000.0'>>>>>> str([0, 5, 9, 9])'[0, 5, 9, 9]'>>>>>> repr([0, 5, 9, 9])'[0, 5, 9, 9]'>>>>>> `[0, 5, 9, 9]`'[0, 5, 9, 9]'

Although all three are similar in nature and functionality, only repr() and `` do exactly the same thing, and using them will deliver the "official" string representation of an object that can be evaluated as a valid Python expression (using the eval() BIF). In contrast, str() has the job of delivering a "printable" string representation of an object, which may not necessarily be acceptable by eval(), but will look nice in a print statement. There is a caveat that while most return values from repr() can be evaluated, not all can:

>>> eval(`type(type))`)  File "<stdin>", line 1    eval(`type(type))`)                    ^SyntaxError: invalid syntax

The executive summary is that repr( ) is Python-friendly while str() produces human-friendly output. However, with that said, because both types of string representations coincide so often, on many occasions all three return the exact same string.

Core Note: Why have both repr() and ``?

Occasionally in Python, you will find both an operator and a function that do exactly the same thing. One reason why both an operator and a function exist is that there are times where a function may be more useful than the operator, for example, when you are passing around executable objects like functions and where different functions may be called depending on the data item. Another example is the double-star ( ** ) and pow() BIF, which performs "x to the y power" exponentiation for x ** y or pow(x,y).


4.6.4. type() and isinstance()

Python does not support method or function overloading, so you are responsible for any "introspection" of the objects that your functions are called with. (Also see the Python FAQ 4.75.) Fortunately, we have the type() BIF to help us with just that, introduced earlier in Section 4.3.1.

What's in a name? Quite a lot, if it is the name of a type. It is often advantageous and/or necessary to base pending computation on the type of object that is received. Fortunately, Python provides a BIF just for that very purpose. type() returns the type for any Python object, not just the standard types. Using the interactive interpreter, let us take a look at some examples of what type() returns when we give it various objects.

>>> type('')<type 'str'>>>>>>> s = 'xyz'>>> type(s)<type 'str'>>>>>>> type(100)<type 'int'>>>> type(0+0j)<type 'complex'>>>> type(0L)<type 'long'>>>> type(0.0)<type 'float'>>>>>>> type([])<type 'list'>>>> type(())<type 'tuple'>>>> type({})<type 'dict'>>>> type(type)<type 'type'>>>>>>> class Foo: pass            # new-style class...>>> foo = Foo()>>> class Bar(object): pass    # new-style class...>>> bar = Bar()>>>>>> type(Foo)<type 'classobj'>>>> type(foo)<type 'instance'>>>> type(Bar)<type 'type'>>>> type(bar)<class '__main__.Bar'>

Types and classes were unified in Python 2.2. You will see output different from that above if you are using a version of Python older than 2.2:

>>> type('')<type 'string'>>>> type(0L)<type 'long int'>>>> type({})<type 'dictionary'>>>> type(type)<type 'builtin_function_or_method'>>>>>>> type(Foo)          # assumes Foo created as in above<type 'class'>>>> type(foo)          # assumes foo instantiated also<type 'instance'>

In addition to type(), there is another useful BIF called isinstance(). We cover it more formally in Chapter 13 (Object-Oriented Programming), but here we can introduce it to show you how you can use it to help determine the type of an object.

Example

We present a script in Example 4.1 that shows how we can use isinstance() and type() in a runtime environment. We follow with a discussion of the use of type() and how we migrated to using isinstance() instead for the bulk of the work in this example.

Example 4.1. Checking the Type (typechk.py)

The function displayNumType() takes a numeric argument and uses the type() built-in to indicate its type (or "not a number," if that is the case).

  1 #!/usr/bin/env python  2  3 def displayNumType(num):  4     print num, 'is',  5     if isinstance(num, (int, long, float, complex)):  6        print 'a number of type:', type(num).__name__  7     else:  8       print 'not a number at all!!'  9  10 displayNumType(-69)  11 displayNumType(9999999999999999999999L)  12 displayNumType(98.6)  13 displayNumType(-5.2+1.9j)  14 displayNumType('xxx')

Running typechk.py, we get the following output:

-69 is a number of type: int9999999999999999999999 is a number of type: long98.6 is a number of type: float(-5.2+1.9j) is a number of type: complexxxx is not a number at all!!

The Evolution of This Example
Original

The same function was defined quite differently in the first edition of this book:

def displayNumType(num):    print num, "is",    if type(num) == type(0):        print 'an integer'    elif type(num) == type(0L):        print 'a long'    elif type(num) == type(0.0):        print 'a float'    elif type(num) == type(0+0j):        print 'a complex number'    else:        print 'not a number at all!!'

As Python evolved in its slow and simple way, so must we. Take a look at our original conditional expression:

if type(num) == type(0)...

Reducing Number of Function Calls

If we take a closer look at our code, we see a pair of calls to type(). As you know, we pay a small price each time a function is called, so if we can reduce that number, it will help with performance.

An alternative to comparing an object's type with a known object's type (as we did above and in the example below) is to utilize the types module, which we briefly mentioned earlier in the chapter. If we do that, then we can use the type object there without having to "calculate it." We can then change our code to only having one call to the type() function:

>>> import types>>> if type(num) == types.IntType...

Object Value Comparison versus Object Identity Comparison

We discussed object value comparison versus object identity comparison earlier in this chapter, and if you realize one key fact, then it will become clear that our code is still not optimal in terms of performance. During runtime, there is always only one type object that represents an integer. In other words, type(0), type(42), type(-100) are always the same object: <type 'int'> (and this is also the same object as types.IntType).

If they are always the same object, then why do we have to compare their values since we already know they will be the same? We are "wasting time" extracting the values of both objects and comparing them if they are the same object, and it would be more optimal to just compare the objects themselves. Thus we have a migration of the code above to the following:

if type(num) is types.IntType... # or type(0)

Does that make sense? Object value comparison via the equal sign requires a comparison of their values, but we can bypass this check if the objects themselves are the same. If the objects are different, then we do not even need to check because that means the original variable must be of a different type (since there is only one object of each type). One call like this may not make a difference, but if there are many similar lines of code throughout your application, then it starts to add up.

Reduce the Number of Lookups

This is a minor improvement to the previous example and really only makes a difference if your application performs makes many type comparisons like our example. To actually get the integer type object, the interpreter has to look up the types name first, and then within that module's dictionary, find IntType. By using from-import, you can take away one lookup:

from types import IntTypeif type(num) is IntType ...

Convenience and Style

The unification of types and classes in 2.2 has resulted in the expected rise in the use of the isinstance() BIF. We formally introduce isinstance() in Chapter 13 (Object-Oriented Programming), but we will give you a quick preview now.

This Boolean function takes an object and one or more type objects and returns true if the object in question is an instance of one of the type objects. Since types and classes are now the same, int is now a type (object) and a class. We can use isinstance() with the built-in types to make our if statement more convenient and readable:

if isinstance(num, int)...

Using isinstance() along with type objects is now also the accepted style of usage when introspecting objects' types, which is how we finally arrive at our updated typechk.py application above. We also get the added bonus of isinstance() accepting a tuple of type objects to check against our object with instead of having an if-elif-else if we were to use only type().

4.6.5. Python Type Operator and BIF Summary

A summary of operators and BIFs common to all basic Python types is given in Table 4.5. The progressing shaded groups indicate hierarchical precedence from highest-to-lowest order. Elements grouped with similar shading all have equal priority. Note that these (and most Python) operators are available as functions via the operator module.

Table 4.5. Standard Type Operators and Built-in Functions

Operator/Function

Description

Result[a]

String representation

  

``

String representation

str

Built-in functions

  

cmp(obj1, obj2)

Compares two objects

int

repr(obj)

String representation

str

str(obj)

String representation

str

type(obj)

Determines object type

type

Value comparisons

  

<

Less than

bool

>

Greater than

bool

<=

Less than or equal to

bool

>=

Greater than or equal to

bool

==

Equal to

bool

!=

Not equal to

bool

<>

Not equal to

bool

Object comparisons

  

is

The same as

bool

is not

Not the same as

bool

Boolean operators

  

not

Logical negation

bool

and

Logical conjunction

bool

or

Logical disjunction

bool


[a] Boolean comparisons return either TRue or False.


Previous Page
Next Page