11. التعبيرات والتصفية وحساب القيم¶
تلميح
تحتاج مقتطفات الشيفرة في هذه الصفحة إلى الاستيرادات التالية إذا كنت خارج وحدة تحكم pyqgis:
1from qgis.core import (
2 edit,
3 QgsExpression,
4 QgsExpressionContext,
5 QgsFeature,
6 QgsFeatureRequest,
7 QgsField,
8 QgsFields,
9 QgsVectorLayer,
10 QgsPointXY,
11 QgsGeometry,
12 QgsProject,
13 QgsExpressionContextUtils
14)
يوفّر QGIS بعض الدعم لتحليل التعبيرات الشبيهة بـ SQL. ولا يُدعم إلا جزء صغير من صياغة SQL. يمكن تقييم التعبيرات إما بوصفها شروطًا منطقية (تُعيد True أو False) أو بوصفها دوالًا (تُعيد قيمة مفردة). راجع التعبيرات في دليل المستخدم للاطلاع على القائمة الكاملة للدوال المتاحة.
تُدعم ثلاثة أنواع أساسية:
العدد --- الأعداد الصحيحة والعشرية كلاهما، مثل
123و3.14السلسلة النصية --- يجب أن تُحاط بعلامات اقتباس مفردة:
'hello world'مرجع العمود --- عند التقييم، يُستبدل المرجع بالقيمة الفعلية للحقل. ولا تُهرَّب الأسماء.
العمليات التالية متاحة:
العوامل الحسابية:
+،-،*،/،^الأقواس: لفرض أولوية العوامل:
(1 + 1) * 3الموجب والسالب الأحاديان:
-12،+5الدوال الرياضية:
sqrt،sin،cos،tan،asin،acos،atanدوال التحويل:
to_int،to_real،to_string،to_dateالدوال الهندسية:
$area،$lengthدوال معالجة الأشكال الهندسية:
$x،$y،$geometry،num_geometries،centroid
والشروط التالية مدعومة:
المقارنة:
=،!=،>،>=،<،<=مطابقة الأنماط:
LIKE(باستخدام % و _)،~(التعبيرات النمطية)الشروط المنطقية:
AND،OR،NOTالتحقق من القيمة NULL:
IS NULL،IS NOT NULL
أمثلة على الشروط:
1 + 2 = 3sin(angle) > 0'Hello' LIKE 'He%'(x > 10 AND y > 10) OR z = 0
أمثلة على التعبيرات المفردة القيمة:
2 ^ 10sqrt(val)$length + 1
11.1. تحليل التعبيرات¶
يوضح المثال التالي كيفية التحقق مما إذا كان يمكن تحليل تعبير معيّن بشكل صحيح:
1exp = QgsExpression('1 + 1 = 2')
2assert(not exp.hasParserError())
3
4exp = QgsExpression('1 + 1 = ')
5assert(exp.hasParserError())
6
7assert(exp.parserErrorString() == '\nIncomplete expression. You might not have finished the full expression.')
11.2. تقييم التعبيرات¶
يمكن استخدام التعبيرات في سياقات مختلفة، مثلًا لتصفية المعالم أو لحساب قيم حقول جديدة. وفي كل الأحوال يجب تقييم التعبير، أي حساب قيمته بتنفيذ خطوات الحساب المحددة، والتي قد تتراوح من عمليات حسابية بسيطة إلى تعبيرات تجميعية.
11.2.1. التعبيرات الأساسية¶
يقيّم هذا التعبير الأساسي عملية حسابية بسيطة:
exp = QgsExpression('2 * 3')
print(exp)
print(exp.evaluate())
<QgsExpression: '2 * 3'>
6
يمكن استخدام التعبير أيضًا للمقارنة، فيُقيَّم إلى 1 (True) أو 0 (False)
exp = QgsExpression('1 + 1 = 2')
exp.evaluate()
# 1
11.2.2. التعبيرات مع المعالم¶
لتقييم تعبير على معلم، يجب إنشاء كائن QgsExpressionContext وتمريره إلى دالة التقييم ليتمكّن التعبير من الوصول إلى قيم حقول المعلم.
يوضح المثال التالي كيفية إنشاء معلم بحقل يُسمى "Column" وكيفية إضافة هذا المعلم إلى سياق التعبير.
1fields = QgsFields()
2field = QgsField('Column')
3fields.append(field)
4feature = QgsFeature()
5feature.setFields(fields)
6feature.setAttribute(0, 99)
7
8exp = QgsExpression('"Column"')
9context = QgsExpressionContext()
10context.setFeature(feature)
11exp.evaluate(context)
12# 99
فيما يلي مثال أكثر اكتمالًا على كيفية استخدام التعبيرات في سياق طبقة متجهية، لحساب قيم حقول جديدة:
1from qgis.PyQt.QtCore import QMetaType
2
3# create a vector layer
4vl = QgsVectorLayer("Point", "Companies", "memory")
5pr = vl.dataProvider()
6pr.addAttributes([QgsField("Name", QMetaType.Type.QString),
7 QgsField("Employees", QMetaType.Type.Int),
8 QgsField("Revenue", QMetaType.Type.Double),
9 QgsField("Rev. per employee", QMetaType.Type.Double),
10 QgsField("Sum", QMetaType.Type.Double),
11 QgsField("Fun", QMetaType.Type.Double)])
12vl.updateFields()
13
14# add data to the first three fields
15my_data = [
16 {'x': 0, 'y': 0, 'name': 'ABC', 'emp': 10, 'rev': 100.1},
17 {'x': 1, 'y': 1, 'name': 'DEF', 'emp': 2, 'rev': 50.5},
18 {'x': 5, 'y': 5, 'name': 'GHI', 'emp': 100, 'rev': 725.9}]
19
20for rec in my_data:
21 f = QgsFeature()
22 pt = QgsPointXY(rec['x'], rec['y'])
23 f.setGeometry(QgsGeometry.fromPointXY(pt))
24 f.setAttributes([rec['name'], rec['emp'], rec['rev']])
25 pr.addFeature(f)
26
27vl.updateExtents()
28QgsProject.instance().addMapLayer(vl)
29
30# The first expression computes the revenue per employee.
31# The second one computes the sum of all revenue values in the layer.
32# The final third expression doesn’t really make sense but illustrates
33# the fact that we can use a wide range of expression functions, such
34# as area and buffer in our expressions:
35expression1 = QgsExpression('"Revenue"/"Employees"')
36expression2 = QgsExpression('sum("Revenue")')
37expression3 = QgsExpression('area(buffer($geometry,"Employees"))')
38
39# QgsExpressionContextUtils.globalProjectLayerScopes() is a convenience
40# function that adds the global, project, and layer scopes all at once.
41# Alternatively, those scopes can also be added manually. In any case,
42# it is important to always go from “most generic” to “most specific”
43# scope, i.e. from global to project to layer
44context = QgsExpressionContext()
45context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(vl))
46
47with edit(vl):
48 for f in vl.getFeatures():
49 context.setFeature(f)
50 f['Rev. per employee'] = expression1.evaluate(context)
51 f['Sum'] = expression2.evaluate(context)
52 f['Fun'] = expression3.evaluate(context)
53 vl.updateFeature(f)
54
55print(f['Sum'])
876.5
11.2.3. تصفية طبقة باستخدام التعبيرات¶
يمكن استخدام المثال التالي لتصفية طبقة وإعادة أي معلم يطابق شرطًا.
1layer = QgsVectorLayer("Point?field=Test:integer",
2 "addfeat", "memory")
3
4layer.startEditing()
5
6for i in range(10):
7 feature = QgsFeature()
8 feature.setAttributes([i])
9 assert(layer.addFeature(feature))
10layer.commitChanges()
11
12expression = 'Test >= 3'
13request = QgsFeatureRequest().setFilterExpression(expression)
14
15matches = 0
16for f in layer.getFeatures(request):
17 matches += 1
18
19print(matches)
7
11.3. معالجة أخطاء التعبيرات¶
قد تحدث أخطاء متعلقة بالتعبيرات أثناء تحليل التعبير أو تقييمه:
1exp = QgsExpression("1 + 1 = 2")
2if exp.hasParserError():
3 raise Exception(exp.parserErrorString())
4
5value = exp.evaluate()
6if exp.hasEvalError():
7 raise ValueError(exp.evalErrorString())