qgis-syntax-expressions
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseqgis-syntax-expressions
QGIS表达式语法参考
Quick Reference
快速参考
Expression Evaluation Pipeline
表达式求值流程
| Step | Class | Purpose |
|---|---|---|
| 1. Parse | | Validate syntax, build AST |
| 2. Context | | Provide variables, fields, scopes |
| 3. Scopes | | Add global/project/layer/feature scopes |
| 4. Evaluate | | Execute and return result |
| 5. Validate | | Check for runtime errors |
| 步骤 | 类 | 用途 |
|---|---|---|
| 1. 解析 | | 验证语法,构建AST |
| 2. 上下文 | | 提供变量、字段、作用域 |
| 3. 作用域 | | 添加全局/项目/图层/要素作用域 |
| 4. 求值 | | 执行并返回结果 |
| 5. 验证 | | 检查运行时错误 |
Expression Syntax Cheatsheet
表达式语法速查表
| Element | Syntax | Example |
|---|---|---|
| Field reference | | |
| String literal | | |
| Number literal | | |
| NULL check | | |
| Comparison | | |
| Logical | | |
| Arithmetic | | |
| Pattern match | | |
| Concatenation | | |
| Conditional | | |
| Geometry vars | | |
| Current geometry | | |
| 元素 | 语法 | 示例 |
|---|---|---|
| 字段引用 | | |
| 字符串字面量 | | |
| 数字字面量 | | |
| NULL值检查 | | |
| 比较运算 | | |
| 逻辑运算 | | |
| 算术运算 | | |
| 模式匹配 | | |
| 字符串拼接 | | |
| 条件判断 | | |
| 几何变量 | | |
| 当前几何对象 | | |
Common Expression Functions
常用表达式函数
| Category | Functions |
|---|---|
| Math | |
| String | |
| Conversion | |
| Date/Time | |
| Geometry | |
| Aggregates | |
| Conditionals | |
| Arrays | |
| Map/Record | |
| Color | |
| 类别 | 函数 |
|---|---|
| 数学 | |
| 字符串 | |
| 类型转换 | |
| 日期/时间 | |
| 几何 | |
| 聚合 | |
| 条件 | |
| 数组 | |
| 映射/记录 | |
| 颜色 | |
Critical Warnings
重要警告
ALWAYS check after creating a . A parser error means the expression string is syntactically invalid and evaluation will fail silently or return NULL.
exp.hasParserError()QgsExpressionALWAYS check after calling . Evaluation errors occur when the expression is syntactically valid but fails at runtime (e.g., field not found, type mismatch).
exp.hasEvalError()exp.evaluate()ALWAYS set up a proper with appropriate scopes when evaluating expressions that reference fields, project variables, or layer properties. Evaluating without context returns NULL for all field references.
QgsExpressionContextNEVER use double quotes for string literals in expressions. Double quotes reference field names: reads the field, is the string literal.
"name"'name'NEVER forget to call before evaluating feature-dependent expressions in a loop. Omitting this causes all features to evaluate against stale or empty data.
context.setFeature(feature)NEVER use inside custom expression functions (). Use instead. Expression functions run during rendering and causes thread-safety issues.
print()@qgsfunctionQgsMessageLogprint()ALWAYS specify in for performance. Use if the function reads arbitrary fields; use if it reads no fields.
referenced_columns@qgsfunction[QgsFeatureRequest.ALL_ATTRIBUTES][]ALWAYS set in if the function accesses . Omitting this causes the geometry to be unavailable.
usesgeometry=True@qgsfunctionfeature.geometry()务必在创建后检查。解析错误表示表达式字符串语法无效,求值将静默失败或返回NULL。
QgsExpressionexp.hasParserError()务必在调用后检查。求值错误发生在表达式语法有效但运行时失败的场景(例如:字段未找到、类型不匹配)。
exp.evaluate()exp.hasEvalError()务必在求值涉及字段、项目变量或图层属性的表达式时,设置包含合适作用域的。如果没有上下文,所有字段引用的求值结果都将是NULL。
QgsExpressionContext切勿在表达式中使用双引号表示字符串字面量。双引号用于引用字段名:表示读取字段,才是字符串字面量。
"name"'name'切勿在循环中求值依赖要素的表达式前忘记调用。省略此步骤会导致所有要素都基于过期或空数据进行求值。
context.setFeature(feature)切勿在自定义表达式函数()中使用。请改用。表达式函数在渲染期间运行,会引发线程安全问题。
@qgsfunctionprint()QgsMessageLogprint()务必在中指定以提升性能。如果函数读取任意字段,请使用;如果不读取任何字段,请使用。
@qgsfunctionreferenced_columns[QgsFeatureRequest.ALL_ATTRIBUTES][]如果函数访问,务必在中设置。省略此步骤会导致几何对象不可用。
feature.geometry()@qgsfunctionusesgeometry=TrueDecision Tree: Choosing the Right Expression Approach
决策树:选择合适的表达式使用方式
Need to use an expression?
|
+-- Filter features? --> QgsFeatureRequest.setFilterExpression()
|
+-- Calculate field values? --> Field Calculator pattern (edit session + evaluate per feature)
|
+-- Drive labeling? --> QgsPalLayerSettings.fieldName + isExpression = True
|
+-- Drive symbology? --> QgsProperty.fromExpression() on symbol/renderer properties
|
+-- Evaluate standalone? --> QgsExpression.evaluate(context)
|
+-- Need custom logic? --> @qgsfunction decorator + QgsExpression.registerFunction()需要使用表达式?
|
+-- 筛选要素? --> QgsFeatureRequest.setFilterExpression()
|
+-- 计算字段值? --> 字段计算器模式(编辑会话 + 逐要素求值)
|
+-- 驱动标注? --> QgsPalLayerSettings.fieldName + isExpression = True
|
+-- 驱动符号化? --> 在符号/渲染器属性上使用QgsProperty.fromExpression()
|
+-- 独立求值? --> QgsExpression.evaluate(context)
|
+-- 需要自定义逻辑? --> @qgsfunction装饰器 + QgsExpression.registerFunction()Essential Patterns
核心使用模式
Pattern 1: Parse and Evaluate an Expression
模式1:解析并求值表达式
python
from qgis.core import (
QgsExpression, QgsExpressionContext, QgsExpressionContextUtils
)
exp = QgsExpression('"population" * 1.05')
if exp.hasParserError():
raise ValueError(f"Parse error: {exp.parserErrorString()}")
context = QgsExpressionContext()
context.appendScopes(
QgsExpressionContextUtils.globalProjectLayerScopes(layer)
)
for feature in layer.getFeatures():
context.setFeature(feature)
value = exp.evaluate(context)
if exp.hasEvalError():
raise ValueError(f"Eval error: {exp.evalErrorString()}")
print(f"Feature {feature.id()}: {value}")python
from qgis.core import (
QgsExpression, QgsExpressionContext, QgsExpressionContextUtils
)
exp = QgsExpression('"population" * 1.05')
if exp.hasParserError():
raise ValueError(f"Parse error: {exp.parserErrorString()}")
context = QgsExpressionContext()
context.appendScopes(
QgsExpressionContextUtils.globalProjectLayerScopes(layer)
)
for feature in layer.getFeatures():
context.setFeature(feature)
value = exp.evaluate(context)
if exp.hasEvalError():
raise ValueError(f"Eval error: {exp.evalErrorString()}")
print(f"Feature {feature.id()}: {value}")Pattern 2: Expression-Based Feature Filtering
模式2:基于表达式的要素筛选
python
from qgis.core import QgsFeatureRequestpython
from qgis.core import QgsFeatureRequestMethod A: expression string directly
方法A:直接使用表达式字符串
request = QgsFeatureRequest().setFilterExpression('"population" >= 50000')
features = list(layer.getFeatures(request))
request = QgsFeatureRequest().setFilterExpression('"population" >= 50000')
features = list(layer.getFeatures(request))
Method B: QgsExpression object
方法B:使用QgsExpression对象
exp = QgsExpression('"name" ILIKE '%lake%'')
request = QgsFeatureRequest(exp)
features = list(layer.getFeatures(request))
undefinedexp = QgsExpression('"name" ILIKE '%lake%'')
request = QgsFeatureRequest(exp)
features = list(layer.getFeatures(request))
undefinedPattern 3: Field Calculator (Update Attributes)
模式3:字段计算器(更新属性)
python
from qgis.core import (
edit, QgsExpression, QgsExpressionContext,
QgsExpressionContextUtils
)
exp = QgsExpression('"population" * 2')
context = QgsExpressionContext()
context.appendScopes(
QgsExpressionContextUtils.globalProjectLayerScopes(layer)
)
with edit(layer):
for f in layer.getFeatures():
context.setFeature(f)
f['doubled_pop'] = exp.evaluate(context)
layer.updateFeature(f)python
from qgis.core import (
edit, QgsExpression, QgsExpressionContext,
QgsExpressionContextUtils
)
exp = QgsExpression('"population" * 2')
context = QgsExpressionContext()
context.appendScopes(
QgsExpressionContextUtils.globalProjectLayerScopes(layer)
)
with edit(layer):
for f in layer.getFeatures():
context.setFeature(f)
f['doubled_pop'] = exp.evaluate(context)
layer.updateFeature(f)Pattern 4: Expression-Based Labeling
模式4:基于表达式的标注
python
from qgis.core import QgsPalLayerSettings, QgsVectorLayerSimpleLabeling
settings = QgsPalLayerSettings()
settings.fieldName = '"name" || \' (\' || "population" || \')\''
settings.isExpression = True
settings.enabled = True
text_format = settings.format()
text_format.setSize(12)
settings.setFormat(text_format)
labeling = QgsVectorLayerSimpleLabeling(settings)
layer.setLabeling(labeling)
layer.setLabelsEnabled(True)
layer.triggerRepaint()python
from qgis.core import QgsPalLayerSettings, QgsVectorLayerSimpleLabeling
settings = QgsPalLayerSettings()
settings.fieldName = '"name" || \' (\' || "population" || \')\''
settings.isExpression = True
settings.enabled = True
text_format = settings.format()
text_format.setSize(12)
settings.setFormat(text_format)
labeling = QgsVectorLayerSimpleLabeling(settings)
layer.setLabeling(labeling)
layer.setLabelsEnabled(True)
layer.triggerRepaint()Pattern 5: Data-Defined Symbology Properties
模式5:数据定义的符号化属性
python
from qgis.core import QgsProperty
symbol = layer.renderer().symbol()python
from qgis.core import QgsProperty
symbol = layer.renderer().symbol()Size driven by expression
由表达式驱动大小
symbol.setDataDefinedSize(
QgsProperty.fromExpression('"population" / 1000')
)
symbol.setDataDefinedSize(
QgsProperty.fromExpression('"population" / 1000')
)
Color driven by expression
由表达式驱动颜色
symbol.setDataDefinedColor(
QgsProperty.fromExpression(
"CASE WHEN "type" = 'city' THEN '#ff0000' ELSE '#0000ff' END"
)
)
layer.triggerRepaint()
undefinedsymbol.setDataDefinedColor(
QgsProperty.fromExpression(
"CASE WHEN "type" = 'city' THEN '#ff0000' ELSE '#0000ff' END"
)
)
layer.triggerRepaint()
undefinedPattern 6: Custom Expression Function
模式6:自定义表达式函数
python
from qgis.core import qgsfunction, QgsExpression
@qgsfunction(args='auto', group='Custom', referenced_columns=[])
def population_density(population, area_km2, feature, parent):
"""
Calculate population density per square kilometer.
<p>Usage: population_density("pop_field", "area_field")</p>
"""
if area_km2 and area_km2 > 0:
return population / area_km2
return Nonepython
from qgis.core import qgsfunction, QgsExpression
@qgsfunction(args='auto', group='Custom', referenced_columns=[])
def population_density(population, area_km2, feature, parent):
"""
Calculate population density per square kilometer.
<p>Usage: population_density("pop_field", "area_field")</p>
"""
if area_km2 and area_km2 > 0:
return population / area_km2
return NoneRegister (call once, e.g., in plugin initGui)
注册(调用一次,例如在插件的initGui中)
QgsExpression.registerFunction(population_density)
QgsExpression.registerFunction(population_density)
Now usable: population_density("population", "area")
现在可使用:population_density("population", "area")
Unregister (call in plugin unload)
注销(在插件unload中调用)
QgsExpression.unregisterFunction('population_density')
---QgsExpression.unregisterFunction('population_density')
---Context Scope Hierarchy
上下文作用域层级
Scopes are stacked from generic to specific. When variable names collide, the most specific scope wins:
Global scope → @qgis_version, @user_full_name, custom global vars
Project scope → @project_title, @project_crs, custom project vars
Layer scope → @layer_name, @layer_id, layer fields
Feature scope → Feature attributes, $geometry, $id, $currentfeature作用域从通用到特定依次堆叠。当变量名冲突时,最特定的作用域优先级最高:
全局作用域 → @qgis_version, @user_full_name, 自定义全局变量
项目作用域 → @project_title, @project_crs, 自定义项目变量
图层作用域 → @layer_name, @layer_id, 图层字段
要素作用域 → 要素属性, $geometry, $id, $currentfeatureAdding Custom Variables
添加自定义变量
python
from qgis.core import QgsExpressionContextUtilspython
from qgis.core import QgsExpressionContextUtilsSet global variable (persists across sessions)
设置全局变量(跨会话持久化)
QgsExpressionContextUtils.setGlobalVariable('my_threshold', 42)
QgsExpressionContextUtils.setGlobalVariable('my_threshold', 42)
Set project variable (saved with project)
设置项目变量(随项目保存)
QgsExpressionContextUtils.setProjectVariable(
QgsProject.instance(), 'analysis_year', 2024
)
QgsExpressionContextUtils.setProjectVariable(
QgsProject.instance(), 'analysis_year', 2024
)
Set layer variable (saved with layer in project)
设置图层变量(随项目中的图层保存)
QgsExpressionContextUtils.setLayerVariable(layer, 'source_date', '2024-01-15')
QgsExpressionContextUtils.setLayerVariable(layer, 'source_date', '2024-01-15')
Access in expressions: @my_threshold, @analysis_year, @source_date
在表达式中访问:@my_threshold, @analysis_year, @source_date
---
---Aggregate Expressions
聚合表达式
Aggregates compute values across features within a layer:
python
undefined聚合函数用于计算图层内多个要素的汇总值:
python
undefinedIn expression strings:
在表达式字符串中:
aggregate('layer_name', 'sum', "population")
aggregate('layer_name', 'sum', "population")
aggregate('layer_name', 'mean', "area", filter:="type" = 'residential')
aggregate('layer_name', 'mean', "area", filter:="type" = 'residential')
Common shorthand (current layer):
常用简写(当前图层):
sum("population")
sum("population")
count("id", filter:="active" = 1)
count("id", filter:="active" = 1)
mean("temperature", group_by:="region")
mean("temperature", group_by:="region")
**ALWAYS** use the `filter` parameter in aggregates to limit the scope. Aggregating an entire large layer without a filter is a performance bottleneck.
---
**务必**在聚合函数中使用`filter`参数来限定作用范围。不对大型图层进行过滤就直接聚合会导致性能瓶颈。
---Reference Links
参考链接
- references/methods.md -- API signatures for QgsExpression, QgsExpressionContext, QgsExpressionContextUtils, @qgsfunction
- references/examples.md -- Complete expression examples for filtering, labeling, symbology, field calculator
- references/anti-patterns.md -- Expression pitfalls and incorrect patterns
- references/methods.md —— QgsExpression、QgsExpressionContext、QgsExpressionContextUtils、@qgsfunction的API签名文档
- references/examples.md —— 用于筛选、标注、符号化、字段计算的完整表达式示例
- references/anti-patterns.md —— 表达式使用陷阱及错误模式