3. Expresiones¶
3.1 Conceptos básicos¶
Una expresión (Declaración) se compone de uno a más operandos y operadores, y se puede obtener un resultado evaluando la expresión. Este resultado se llama el valor de la expresión. El operando puede ser un valor literal, una variable, una llamada de función o una subexpresión, etc. Las expresiones y operadores simples también se pueden combinar en expresiones más complejas. Similar a las cuatro operaciones aritméticas, la precedencia de los operadores afecta el orden de evaluación de las expresiones. Cuanto mayor sea la precedencia del operador, antes se evaluará la expresión.
Operadores y expresiones¶
Berry proporciona algunos operadores unarios y operadores binarios. Por
ejemplo, el operador AND lógico &&
es un operador binario, y el
operador de negación lógica !
es un operador unario. Algunos
operadores pueden ser operadores unarios u operadores binarios. El
significado específico de tales operadores depende del contexto. Por
ejemplo, el operador -
es un símbolo unario en la expresión -1
,
pero es un signo menos binario en la expresión 1-2
.
Expresión de combinación de operadores¶
Tanto el lado izquierdo como el derecho de un operador binario pueden ser subexpresiones, por lo que puede usar operadores binarios para combinar expresiones. Una expresión más compleja suele tener varios operadores y operandos. En este momento, el orden de evaluación de cada subexpresión en la expresión puede afectar el valor de la expresión. La precedencia y asociatividad de los operadores garantizan la unicidad del orden de evaluación de la expresión. Por ejemplo, una expresión combinada:
1 + 10/2 * 3
Las cuatro operaciones aritméticas de uso diario calcularán primero la
expresión de división 10/2
, luego la expresión de multiplicación y
finalmente la expresión de suma. Esto se debe a que la multiplicación y
la división tienen mayor prioridad que la suma.
Tipo de operando¶
En la operación de expresiones, los operandos pueden tener tipos que no
coincidan con los operadores. Además, los operadores binarios
normalmente requieren que los operandos izquierdo y derecho sean del
mismo tipo. La expresión '10'+10
es incorrecta. No puede agregar una
cadena a un número entero. El problema con la expresión -'b'
es que
no puedes tomar un valor negativo en una cadena. A veces, un operador
binario tiene diferentes tipos de operandos pero puede realizar
operaciones. Por ejemplo, al agregar un número entero a un número real,
el objeto entero se convertirá en un número real y se agregará a otro
objeto de número real. Los operadores lógicos AND y OR lógicos permiten
que los operandos a ambos lados del operador sean de cualquier tipo. En
expresiones lógicas, siempre se convertirán al tipo booleano
de
acuerdo con ciertas reglas.
Otra situación es que los operadores pueden sobrecargarse al usar clases personalizadas. En esencia, puede interpretar este operador arbitrariamente y depende de usted decidir qué tipo de operando debe ser.
3.1.1 Prioridad y asociatividad¶
En una expresión compuesta de varios operadores, la precedencia y la asociatividad de los operadores determinan el orden de evaluación de las expresiones. La precedencia y asociatividad de cada operador se dan en la Tabla 2 .
La precedencia especifica el orden de evaluación entre diferentes
operadores, y las expresiones con operadores de mayor precedencia se
evaluarán primero. Por ejemplo, el proceso de evaluar la expresión
1+2*3
calculará primero el resultado de 2*3
y luego el resultado
de la expresión de suma. El uso de paréntesis puede mejorar el orden de
evaluación de las expresiones de baja prioridad. Por ejemplo, en la
evaluación de la expresión (1+2)*3
, primero se calcula el resultado
de la expresión 1+2
entre paréntesis y luego se calcula la expresión
de multiplicación fuera de los paréntesis.
La asociatividad se refiere al orden de evaluación de los operandos en
ambos lados del operador, donde los operandos pueden ser subexpresiones.
Por ejemplo, en la expresión de suma expr1 + expr2
, el valor de
expr1
se calcula primero y luego el valor de expr2
, porque el
operador de suma es asociativo por la izquierda.
prioridad |
Operador |
Descripción |
Asociatividad |
---|---|---|---|
1 |
|
Símbolo de agrupación |
|
2 |
|
Operación de campo |
izquierda |
3 |
|
Signo negativo, negación lógica, cambio de bit |
izquierda |
4 |
|
M ultiplicación, división y resto |
izquierda |
5 |
|
Suma, resta |
izquierda |
6 |
|
Mover a la izquierda, mover a la derecha |
izquierda |
7 |
|
Bit a bit Y |
izquierda |
8 |
|
XOR bit a bit |
izquierda |
9 |
|
Bit a bit O |
izquierda |
10 |
|
Operador de concatenación |
izquierda |
11 |
|
Mayor que, mayor que o igual a |
izquierda |
12 |
|
Igual a, no igual a |
izquierda |
13 |
|
Y lógico |
izquierda |
14 |
|
O lógico |
izquierda |
15 |
|
Operador condicional |
derecha |
16 |
|
Asignación |
derecha |
Tabla 2: Lista de operadores
Utilice corchetes para aumentar la prioridad¶
Los paréntesis se pueden usar cuando necesitamos que los operadores con menor precedencia se evalúen primero. Durante la evaluación de expresiones, primero se calcula el valor de la expresión entre paréntesis. En otras palabras, para toda la expresión, la expresión entre paréntesis es equivalente a un operando, independientemente de la composición de la expresión entre paréntesis.
3.2 Operador¶
3.2.1 Operadores aritméticos¶
Los operadores aritméticos se utilizan para implementar operaciones aritméticas. Estos operadores son similares a los símbolos matemáticos que solemos usar. Los operadores aritméticos provistos por Berry se muestran en la Tabla 3 .
Operador |
Descripción |
Ejemplo |
---|---|---|
|
menos unario |
|
|
Concatenación más/cadena |
|
|
signo menos |
|
|
Signo de multiplicación |
|
|
Signo de división |
|
|
Toma el resto |
|
Tabla 3: Operador aritmético
Operador binario +
Además de ser un signo más, también es una
concatenación de cadenas. Cuando el operando de este operador es una
cadena, la concatenación de cadenas se realizará para concatenar dos
cadenas en una cadena más larga. Para ser precisos, +
como
concatenación de cadenas ya no está en la categoría de operadores
aritméticos.
El operador binario %
es el símbolo de resto. Sus operandos deben
ser números enteros. El resultado de la operación de resto es el resto
después de dividir el operando izquierdo por el operando derecho. Por
ejemplo, el resultado de 11%4
es 3
. El tipo de número real no
puede ser divisible, por lo que no se admite el resto.
En general, los operadores aritméticos no cumplen la ley conmutativa.
Por ejemplo, los valores de las expresiones 2/4
y 4/2
no son
iguales.
Todos los operadores aritméticos se pueden sobrecargar en la clase. Los operadores sobrecargados no están necesariamente limitados a su diseño funcional original, sino que son determinados por el programador.
3.2.2 Operadores relacionales¶
Los operadores relacionales se utilizan para comparar la magnitud de los operandos. Los seis operadores relacionales soportados por Berry se dan en la Tabla 4 .
Operador |
Descripción |
Ejemplo |
---|---|---|
|
Menor que |
|
|
Menor o igual que |
|
|
Igual |
|
|
No es igual a |
|
|
Mayor o igual a |
|
|
Mayor qu e |
|
Tabla 4: Operador relacional
Al comparar la relación de magnitud de los operandos o juzgar si los
operandos son iguales, la evaluación de la expresión relacional
producirá un resultado booleano. Cuando se cumple la relación, el valor
de la expresión de la relación es “verdadero”, de lo contrario, es
“falso”. Los operadores relacionales ==
y !=
pueden usar
cualquier tipo de operando y permiten que los operandos izquierdo y
derecho tengan diferentes tipos. Otros operadores relacionales permiten
el uso de las siguientes combinaciones de operandos:
integer relop integer
real relop real
integer relop real
real relop integer
string relop string
En operaciones relacionales, el signo igual ==
y el signo de
desigualdad !=
satisfacen la ley conmutativa. Si los operandos
izquierdo y derecho son del mismo tipo o ambos son de tipo numérico
(número entero y número real), los operandos se consideran iguales según
el valor de los operandos; de lo contrario, los operandos se consideran
desiguales. La igualdad y la desigualdad son operaciones recíprocas: si
a==b
es verdadero, entonces a!=b
es falso, y viceversa. Otros
operadores relacionales no satisfacen la ley conmutativa, pero tienen
las siguientes propiedades: <
y >=
son operaciones recíprocas, y
>
y <=
son operaciones recíprocas. Las operaciones relacionales
requieren que los operandos sean del mismo tipo, de lo contrario es una
expresión incorrecta.
Las instancias pueden sobrecargar a los operadores como métodos. Si el operador relacional está sobrecargado, el programa debe garantizar las propiedades anteriores.
Entre los operadores relacionales, los operadores ==
y !=
tienen
requisitos más relajados que <
, <=
, >
y >=
, que solo
permiten comparaciones entre los mismos tipos. En el desarrollo de un
programa real, el juicio de igualdad o desigualdad suele ser más simple
que el juicio de tamaño. Es posible que algunos objetos de operación no
puedan juzgar el tamaño, pero solo pueden juzgar la igualdad o
desigualdad. Este es el caso del tipo booleano.
Operadores logicos¶
Los operadores lógicos se dividen en tres tipos: AND lógico, OR lógico y NOT lógico. Como se muestra en la Tabla 5 .
Operador |
Descripción |
Ejemplo |
---|---|---|
|
Y lógico |
|
|
O lógico |
|
|
Negación lógica |
|
Tabla 5: Operadores logicos
Para el operador lógico AND, cuando los valores de ambos operandos son “verdaderos”, el valor de la expresión lógica es “verdadero”, de lo contrario, es “falso”.
Para el operador lógico OR, cuando los valores de ambos operandos son
falso
, el valor de la expresión lógica es falso
, de lo contrario
es verdadero
.
El papel del operador de negación lógica es cambiar el estado lógico del operando. Cuando el valor del operando es “verdadero”, el valor de la expresión lógica es “falso”, de lo contrario, el valor es “verdadero”.
Los operadores lógicos requieren que el operando sea de tipo booleano, y si el operando no es de tipo booleano, se convertirá. Consulte la sección [Capitulo-2: Tipo booleano] para conocer las reglas de conversión.
Las operaciones lógicas utilizan una estrategia de evaluación llamada Evaluación de cortocircuito. Esta estrategia de evaluación es: para el operador lógico AND, el segundo operando se evaluará si y solo si el operando de la izquierda es verdadero; para el operador lógico OR, si y solo si el operando izquierdo es falso evaluará el operando derecho. La naturaleza de la evaluación de cortocircuito hace que no se ejecute todo el código de la expresión lógica.
Operador bit a bit¶
Los operadores de bits pueden implementar algunas operaciones de bits binarios, y las operaciones de bits solo se pueden usar en tipos enteros. La información detallada de los operadores de bit se muestra en la Tabla 6 . La operación de bits se refiere a la operación de bits binarios directamente en números enteros. Las operaciones lógicas se pueden extender a operaciones de bits. Tomando AND lógico como ejemplo, podemos realizar esta operación en cada bit binario para lograr AND bit a bit, como 110b AND 011b = 010b. Las operaciones de bits también admiten operaciones de cambio, que mueven números de forma binaria.
Operador |
Ejemplo |
|
---|---|---|
|
Negar |
|
|
Bit a bit y |
|
|
Bit a bit o |
|
|
O exclusivo bit a bit |
|
|
Desplazar a la izquierda |
|
|
Desplazar a la derecha |
|
Tabla 6: Operador bit a bit
Aunque solo se puede usar para números enteros, las operaciones con bits
siguen siendo versátiles. Las operaciones de bits pueden implementar
muchas técnicas de optimización. En muchos algoritmos, el uso de
operaciones de bits puede ahorrar mucho código. Por ejemplo, para
determinar si un número n
es una potencia de 2, podemos juzgar si el
resultado de n & (n - 1)
es 0
. En algunos lenguajes con alta
eficiencia de ejecución, las operaciones de cambio también se pueden
usar para optimizar la multiplicación y la división (por lo general, no
hay un efecto obvio en los lenguajes de secuencias de comandos).
El operador AND bit a bit “&
” es un operador binario, que realiza la
operación AND binaria de dos operandos enteros: solo cuando los bits
binarios correspondientes a los operandos son todos 1
, el resultado
es 1
. Por ejemplo, 1110b & 0111b = 0110b.
El operador OR bit a bit “|
” es un operador binario, que realiza una
operación OR de bits binarios en dos operandos enteros: solo cuando los
bits binarios correspondientes a los operandos son ambos 0
, el bit
del resultado es 0
. Por ejemplo, 1000b | 0001b = 1001b.
El operador OR exclusivo bit a bit “^
” es un operador binario, que
realiza una operación OR exclusiva binaria en dos operandos enteros:
cuando los bits binarios correspondientes a los operandos son
diferentes, el valor de bit del resultado es 1
. Por ejemplo,
1100b ^ 0101b = 1001b.
El operador de desplazamiento a la izquierda “<<
” es un operador
binario, que mueve el operando izquierdo hacia la izquierda el número de
bits especificado por el operando derecho sobre una base binaria. Por
ejemplo, 00001010b << 3 = 01010000b. El operador de
desplazamiento a la derecha “>>
” es un operador binario, que
desplaza el operando izquierdo hacia la derecha el número de bits
especificado por el operando derecho en un binario. base. Por ejemplo,
10100000b >> 3 = 00010100b.
El operador de inversión bit a bit “~
” es un operador unario, y el
resultado de la expresión es invertir el valor de cada bit binario del
operando. Por ejemplo, ∼
10100011b = 01011100b.
Los siguientes son algunos ejemplos del uso de operaciones con bits. Por lo general, no usamos binario directamente. Los resultados de los ejemplos se han convertido en bases comunes.
1 << 1 # 2
168 >> 4 # 10
456 & 127 # 72
456 | 127 # 511
0xA5 ^ 0x5A # 255
~2 # -3
Operador de asignación¶
El operador de asignación solo aparece en la expresión de asignación y el operando del operador debe ser un objeto de escritura. La expresión de asignación no tiene resultado, por lo que no se pueden utilizar operaciones de asignación continua.
Operador de asignación simple¶
El operador de asignación simple =
se puede utilizar para la
asignación de variables. Si la variable de operando de la izquierda no
está definida, se definirá la variable. El operador de asignación se
utiliza para vincular el valor del operando derecho con el operando
izquierdo. Este proceso también se llama “asignación”. Por lo tanto, el
operando izquierdo no puede ser una constante, ni puede ser ningún
objeto que no se pueda escribir. Estas son algunas expresiones legales
de asignación:
a = 45 b ='string' c = 0
Y la siguiente expresión de asignación es incorrecta:
1 = 5 # Tratando de asignar una constante 1
a = b = 0 # Asignación continua
Al asignar tipos nil
, enteros, reales y booleanos a variables, el
valor del objeto se pasará al operando izquierdo, pero para otros tipos,
la operación de asignación simplemente pasa la referencia del objeto al
operando izquierdo. Dado que las cadenas, las funciones y los tipos de
clase son de solo lectura, todas las referencias que pasan no tendrán
efectos secundarios, pero debe tener mucho cuidado con los tipos de
instancia.
Operador de asignación compuesto¶
Los operadores de asignación compuestos son operadores que combinan operadores binarios y operadores de asignación. Son extensiones prácticas de operadores de asignación simples. Los operadores de asignación compuestos pueden simplificar la escritura de algunas expresiones. La Tabla 7 enumera todos los operadores de asignación compuestos
Operador |
Descripción |
---|---|
|
Asignación de adición |
|
Asignación de resta |
|
Asignación de multiplicación |
|
Asignación de división |
|
Asignación de resto |
|
Asignación AND bit a bit |
|
Asignación OR bit a bit |
|
Asignación XOR bit a bit |
|
Asignación de desplazamiento a la izquierda |
|
Asignación de desplazamiento a la derecha |
Tabla 7: Operador de bits
La expresión de asignación compuesta realiza la operación binaria
correspondiente al operador de asignación compuesta en el operando
izquierdo y el operando derecho, y luego asigna el resultado al operando
izquierdo. Tomando +=
como ejemplo, la expresión a += b
es
equivalente a a = a + b
. El operador de asignación compuesto también
es un operador de asignación, por lo que tiene una prioridad más baja.
El operador binario correspondiente al operador de asignación compuesto
siempre se evalúa después del operando derecho, por lo que una expresión
como a *= 1 + 2
debería ser equivalente a a = a * (1 + 2)
.
A diferencia del operador de asignación simple, el operando izquierdo del operador de asignación compuesto debe participar en la evaluación, por lo que la expresión de asignación compuesta no tiene la función de definir variables. El operador de asignación en sí no se puede sobrecargar en la clase. Los usuarios solo pueden sobrecargar el operador binario correspondiente al operador de asignación compuesto. Esto también asegura que el operador de asignación compuesto siempre se ajustará a las características básicas de las operaciones de asignación.
Operador de dominio y operador de subíndice
El operador de dominio .
se utiliza para acceder a un atributo o
miembro de un objeto. Puede utilizar operadores de dominio para ambos
tipos de módulos e instancias:
l = list[]
l.push('item 0')
s = l.item(0) # 'item 0'
El operador de subíndice []
se utiliza para acceder a los elementos
de un objeto, por ejemplo
l[2] = 10 # Read by index
n = l[2] # Write by index
Las clases que admiten la lectura de subíndices deben implementar el
método item
y las clases que admiten la escritura de subíndices
deben implementar el método setitem
. El mapa y la lista en el
contenedor estándar implementan estos dos métodos, por lo que admiten la
lectura y escritura mediante el operador de subíndice. La cadena admite
la lectura de subíndices, pero no admite la escritura de subíndices (las
cadenas son valores de solo lectura):
'string'[2] #'r'
'string'[2] ='a' # error: valor 'string' no admite asignación de índice
Actualmente, las cadenas admiten subíndices enteros y el rango de subíndices no puede exceder la longitud de la cadena.
Operador condicional¶
El operador condicional (? :
) es similar a la declaración if
else, pero la primera puede usarse en expresiones. La forma de uso del
operador condicional es:
cond ? expr1 : expr2
cond es la expresión utilizada para juzgar la condición. El proceso de evaluación del operador condicional es: primero encuentra el valor de cond, si la condición es verdadera, evalúa expr1 y devuelve el valor, de lo contrario, el valor de expr2 ] Evalúa y devuelve el valor. expr1 y expr2 pueden tener diferentes tipos, por lo que lo siguiente es correcto:
resultado = alcance < 6 ? 'malo' : alcance
Esta expresión primero determina si alcance
es menor que 6
, si
lo es, devuelve malo
, de lo contrario, devuelve el valor de
alcance
. Independientemente de la condición de la expresión
condicional, solo se ejecutará uno de expr1 o expr2, similar a
la característica de cortocircuito de las operaciones lógicas AND y
lógicas OR.
Operadores de condiciones anidadas¶
Un operador condicional se puede anidar en otro operador condicional, es decir, la expresión condicional se puede usar como cond o expr de otra expresión condicional. Por ejemplo, use expresiones condicionales para dividir puntajes en tres niveles: excelente, bueno y malo:
resultado = alcance >= 9 ? 'excelente' : alcance >= 6 ? 'bueno' : 'malo'
La primera condición comprueba si la puntuación no es inferior a 9
puntos. Si es así, ejecute la rama después de ?
y devuelva
'excelente'
; de lo contrario, ejecute la rama después de :
, que
también es una expresión condicional. La condición comprueba si la
puntuación no es inferior a 6
, si lo es, devuelve 'bueno'
, de lo
contrario, devuelve 'malo'
.
El operador condicional satisface la asociatividad correcta, por lo que el valor de la expresión de bifurcación debe evaluarse primero para obtener el valor de la expresión condicional. Por lo tanto, en una expresión condicional anidada, la expresión condicional anidada se evalúa primero y luego se evalúa la expresión condicional externa.
Prioridad de los operadores condicionales¶
Dado que la precedencia de las expresiones condicionales es muy baja (sólo superada por los operadores de asignación), a menudo es necesario agregar paréntesis fuera de las expresiones condicionales. Por ejemplo, cuando se usa una expresión condicional como operando de una expresión aritmética, los paréntesis tendrán diferentes efectos en el resultado:
resultado = 10 * (signo < 0 ? -1 : 1) # el resultado es -10 ó 10
resultado = 10 * signo < 0 ? -1 : 1 # el resultado es -1 ó 1
El resultado de la primera expresión es correcto, y la segunda expresión
toma 10 * signo < 0
como condición a juzgar, lo que no cumple con la
expectativa de la expresión condicional como el operando derecho de la
multiplicación.
Operador de concatenación¶
Operador +
¶
Cuando los operandos izquierdo y derecho son cadenas, el operador +
se usa para conectar las dos cadenas, y la nueva cadena obtenida es el
valor de la expresión. Por lo tanto, este operador se usa a menudo para
la concatenación de cadenas:
resultado ='abc' + '123' # el resultado es 'abc123'
Los operadores +
también se pueden usar para conectar dos instancias
de lista:
resultado = [1, 2] + [3, 4] # el resultado es [1, 2, 3, 4]
A diferencia del método list.push
, el operador +
fusiona dos
listas en un objeto de lista más grande, con los elementos del operando
izquierdo al principio de la lista de resultados y los elementos del
operando derecho al final de la lista de resultados
Operador ..
¶
..
es un operador especial. Si el operando izquierdo es una cadena,
el comportamiento de la expresión es concatenar los operandos izquierdo
y derecho en una nueva cadena (conversión automática si el operando
derecho no es una cadena):
resultado ='abc' + 123 # el resultado es 'abc123'
El operador ..
se usa a menudo cuando se concatena una cadena y un
valor que no es una cadena. Si el operando izquierdo es una instancia de
lista, el operador ..
agregará el operando derecho al final de la
lista y luego usará esta lista como el valor de la expresión:
resultado ='abc' + 123 # el resultado es 'abc123'
Este proceso modificará directamente el operando izquierdo, que es muy
similar al método push
de list
(excepto las cadenas que son
objetos inmutables). La operación de unión de la lista se puede ejecutar
en cadena:
resultado = [1, 2] .. 3 .. 4 # el resultado es [1, 2, 3, 4]
Todos los valores en este proceso se agregarán al objeto de lista más a la izquierda.
Si los operandos izquierdo y derecho son enteros, utilice el operador
..
para obtener un objeto de rango de enteros:
resultado = 1 .. 10 # el resultado es (1..10)
Este objeto se utiliza para representar un intervalo cerrado de enteros, donde el operando izquierdo es el límite inferior y el operando derecho es el límite superior. Dichos objetos de rango de enteros se utilizan a menudo para la iteración.